diff --git a/packages/transform/STATUS-15-16.md b/packages/transform/STATUS-15-16.md index dd3552ad..57a6cee5 100644 --- a/packages/transform/STATUS-15-16.md +++ b/packages/transform/STATUS-15-16.md @@ -1 +1,57 @@ -not started — see previous status docs for format style. \ No newline at end of file +# PostgreSQL v15-to-v16 AST Transformer Status + +## Current Status: **IN PROGRESS** 🟡 +- **Test Pass Rate**: 184/258 tests passing (71.3% success rate) +- **Branch**: `pg15-pg16-transformer` +- **PR**: [#175](https://github.com/launchql/pgsql-parser/pull/175) + +## Progress Summary +Started from a basic skeleton transformer and systematically implemented node wrapping and transformation logic across all node types. Made significant progress improving test pass rate from initial ~30% to current 71.3%. + +## Key Achievements +- ✅ Implemented comprehensive node transformation methods for 100+ node types +- ✅ Fixed node wrapping issues across SelectStmt, InsertStmt, UpdateStmt, DeleteStmt +- ✅ Resolved PartitionSpec strategy mapping in CreateStmt method +- ✅ Added proper Array handling to transform method for nested node processing +- ✅ Established stable baseline of 184/258 tests passing locally + +## Current Challenge: Negative Integer Transformation +**Root Issue**: PG15 produces `"ival": {}` (empty objects) where PG16 expects `"ival": {"ival": -3}` for negative integers in A_Const nodes. + +**Analysis Completed**: +- Created detailed debug scripts to analyze transformation flow +- Identified that A_Const method calls `this.transform()` on empty ival objects +- Empty objects `{}` don't get routed to Integer method due to missing node wrapper structure +- Need targeted fix that distinguishes between zero values (should remain empty) and negative values (need nested structure) + +**Attempted Solutions**: +- ❌ Broad A_Const fix (transforms all empty ival objects) - caused test pass rate to drop to 144/258 +- ❌ Context-based detection (constraint/ALTER TABLE contexts) - caused test pass rate to drop to 174/258 +- ✅ Successfully reverted to stable 184/258 baseline after testing approaches +- 🔄 Dual-parse approach explored but @pgsql/parser returns empty objects for all SQL queries + +## Debug Tools Created +- `debug_transformation_flow_detailed.js` - Analyzes exact transformation flow for negative integers +- `debug_sql_value_analysis.js` - Compares PG15 vs PG16 behavior across test cases +- `debug_ival_contexts.js` - Analyzes empty ival contexts across different SQL scenarios +- `debug_alternative_approach.js` - Explores alternative detection methods beyond context analysis +- `debug_insert_negative.js` - Tests specific INSERT statement with negative value +- `debug_zero_vs_negative.js` - Compares zero vs negative value handling +- `debug_context_analysis.js` - Analyzes context-dependent transformation patterns + +## Next Steps +1. Investigate alternative approaches beyond context-based and dual-parse methods +2. Consider advanced pattern matching or heuristic detection for negative integer cases +3. Explore selective transformation targeting only high-confidence scenarios +4. Verify specific failing test cases like `alter_table-234.sql` +5. Continue systematic improvement of remaining 74 failing tests + +## Test Categories +- **Passing (184)**: Basic node transformations, most SQL constructs +- **Failing (74)**: Primarily negative integer transformations, some complex nested structures + +## Technical Notes +- Following patterns from v13-to-v14 transformer as reference +- Focus only on v15-to-v16 transformer per user instructions +- Ignoring CI failures per user directive, focusing on local test improvements +- Maintaining systematic approach to avoid regressions \ No newline at end of file diff --git a/packages/transform/TODO.md b/packages/transform/TODO.md new file mode 100644 index 00000000..0015c103 --- /dev/null +++ b/packages/transform/TODO.md @@ -0,0 +1,30 @@ +# TODO: Transform Package Improvements + +## Type Safety Improvements + +### Add Return Type Annotations to Transformer Methods +- **Priority**: High +- **Description**: Add proper TypeScript return type annotations to all transformer methods in v15-to-v16.ts (and other transformers) +- **Benefit**: Would catch structural issues like double-wrapping at compile time instead of runtime +- **Example**: + ```typescript + TypeName(node: PG15.TypeName, context: TransformerContext): { TypeName: PG16.TypeName } { + // implementation + } + ``` +- **Impact**: Prevents bugs like the double-wrapping issue we encountered where `{"TypeName": {"TypeName": {...}}}` was produced instead of `{"TypeName": {...}}` + +### Improve Type Definitions +- Add stricter typing for node transformation methods +- Consider using mapped types for consistent return type patterns +- Add compile-time validation for node wrapping consistency + +## Testing Improvements +- Add unit tests for individual transformer methods +- Create focused test cases for edge cases like empty Integer nodes +- Improve error messages in transformation mismatches + +## Documentation +- Document transformation patterns and conventions +- Add examples of proper node wrapping +- Document debugging strategies for transformation issues diff --git a/packages/transform/analyze_15_16_ci_failures.js b/packages/transform/analyze_15_16_ci_failures.js new file mode 100644 index 00000000..c6772c17 --- /dev/null +++ b/packages/transform/analyze_15_16_ci_failures.js @@ -0,0 +1,104 @@ +const fs = require('fs'); + +function analyze15To16CIFailures() { + const logFile = '/home/ubuntu/full_outputs/gh_run_view_log_fail_1751134577.6148772.txt'; + + try { + const content = fs.readFileSync(logFile, 'utf8'); + + const lines = content.split('\n'); + const failures15to16 = []; + let currentFailure = null; + let isIn15to16 = false; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + if (line.includes('FAIL __tests__/kitchen-sink/15-16/')) { + isIn15to16 = true; + if (currentFailure) { + failures15to16.push(currentFailure); + } + currentFailure = { + testFile: line.split('FAIL ')[1], + errors: [], + fullContext: [] + }; + } else if (line.includes('FAIL __tests__/kitchen-sink/') && !line.includes('15-16')) { + isIn15to16 = false; + if (currentFailure && isIn15to16) { + failures15to16.push(currentFailure); + currentFailure = null; + } + } + + if (isIn15to16 && currentFailure) { + currentFailure.fullContext.push(line); + + if (line.includes('- Expected') || line.includes('+ Received') || + line.includes('ival') || line.includes('Integer')) { + const errorContext = lines.slice(Math.max(0, i-3), i+7).join('\n'); + currentFailure.errors.push(errorContext); + } + } + } + + if (currentFailure && isIn15to16) { + failures15to16.push(currentFailure); + } + + console.log('=== 15-16 CI FAILURE ANALYSIS ==='); + console.log(`Total 15-16 failures found: ${failures15to16.length}`); + + const errorPatterns = { + 'ival_empty_to_nested': 0, + 'integer_wrapping': 0, + 'negative_integer': 0, + 'missing_node_wrapping': 0 + }; + + failures15to16.forEach(f => { + f.errors.forEach(error => { + if (error.includes('ival') && error.includes('{}') && error.includes('ival":')) { + errorPatterns.ival_empty_to_nested++; + } + if (error.includes('Integer') && error.includes('+') && error.includes('-')) { + errorPatterns.integer_wrapping++; + } + if (error.includes('-3') || error.includes('negative')) { + errorPatterns.negative_integer++; + } + if (error.includes('+ ') && error.includes('Object {')) { + errorPatterns.missing_node_wrapping++; + } + }); + }); + + console.log('\n=== 15-16 ERROR PATTERNS ==='); + Object.entries(errorPatterns).forEach(([pattern, count]) => { + console.log(`${pattern}: ${count} occurrences`); + }); + + console.log('\n=== DETAILED 15-16 FAILURES ==='); + failures15to16.slice(0, 3).forEach((f, i) => { + console.log(`\n--- Failure ${i+1}: ${f.testFile} ---`); + if (f.errors.length > 0) { + console.log(f.errors[0].substring(0, 800)); + } else { + console.log('No specific error patterns found, showing context:'); + console.log(f.fullContext.slice(-20).join('\n').substring(0, 800)); + } + console.log('...\n'); + }); + + console.log('\n=== COMPARISON WITH LOCAL FAILURES ==='); + console.log('CI shows 148 failures in 15-16 transformer'); + console.log('Local shows 74 failures in 15-16 transformer'); + console.log('Difference suggests CI may be testing additional scenarios or environment differences'); + + } catch (error) { + console.error('Error analyzing CI failures:', error.message); + } +} + +analyze15To16CIFailures(); diff --git a/packages/transform/analyze_ci_failures.js b/packages/transform/analyze_ci_failures.js new file mode 100644 index 00000000..ae3b0d9b --- /dev/null +++ b/packages/transform/analyze_ci_failures.js @@ -0,0 +1,92 @@ +const fs = require('fs'); + +function analyzeCIFailures() { + const logFile = '/home/ubuntu/full_outputs/gh_run_view_log_fail_1751134169.160914.txt'; + + try { + const content = fs.readFileSync(logFile, 'utf8'); + + const lines = content.split('\n'); + const failures = []; + let currentFailure = null; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + if (line.includes('FAIL __tests__/kitchen-sink/')) { + const match = line.match(/FAIL __tests__\/kitchen-sink\/(\d+-\d+)\//); + if (match) { + if (currentFailure) { + failures.push(currentFailure); + } + currentFailure = { + transformer: match[1], + testFile: line.split('FAIL ')[1], + errors: [] + }; + } + } + + if (currentFailure && (line.includes('- Expected') || line.includes('+ Received'))) { + const errorContext = lines.slice(Math.max(0, i-5), i+10).join('\n'); + currentFailure.errors.push(errorContext); + } + } + + if (currentFailure) { + failures.push(currentFailure); + } + + console.log('=== CI FAILURE ANALYSIS ==='); + console.log(`Total failures found: ${failures.length}`); + + const transformerCounts = {}; + failures.forEach(f => { + transformerCounts[f.transformer] = (transformerCounts[f.transformer] || 0) + 1; + }); + + console.log('\n=== FAILURES BY TRANSFORMER ==='); + Object.entries(transformerCounts).forEach(([transformer, count]) => { + console.log(`${transformer}: ${count} failures`); + }); + + const errorPatterns = { + 'str_to_sval': 0, + 'missing_wrapping': 0, + 'ival_issues': 0 + }; + + failures.forEach(f => { + f.errors.forEach(error => { + if (error.includes('"str":') && error.includes('"sval":')) { + errorPatterns.str_to_sval++; + } + if (error.includes('+ ') && error.includes('Object {')) { + errorPatterns.missing_wrapping++; + } + if (error.includes('ival')) { + errorPatterns.ival_issues++; + } + }); + }); + + console.log('\n=== ERROR PATTERNS ==='); + Object.entries(errorPatterns).forEach(([pattern, count]) => { + console.log(`${pattern}: ${count} occurrences`); + }); + + const my_failures = failures.filter(f => f.transformer === '15-16').slice(0, 3); + console.log('\n=== SAMPLE 15-16 FAILURES ==='); + my_failures.forEach((f, i) => { + console.log(`\n--- Failure ${i+1}: ${f.testFile} ---`); + if (f.errors.length > 0) { + console.log(f.errors[0].substring(0, 500) + '...'); + } + }); + + } catch (error) { + console.error('Error analyzing CI failures:', error.message); + } +} + +analyzeCIFailures(); diff --git a/packages/transform/debug_a_const.js b/packages/transform/debug_a_const.js new file mode 100644 index 00000000..337fcaa7 --- /dev/null +++ b/packages/transform/debug_a_const.js @@ -0,0 +1,74 @@ +const { Parser } = require('@pgsql/parser'); +const { ASTTransformer } = require('./dist/transformer'); + +async function debugAConstTransformation() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + const transformer = new ASTTransformer(); + + const testCases = [ + "insert into atacc2 (test2) values (-3)", + "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)", + "SELECT -1", + "SELECT -3" + ]; + + console.log("=== DEBUGGING A_CONST TRANSFORMATION PATTERNS ==="); + + for (const sql of testCases) { + console.log(`\n=== SQL: ${sql} ===`); + + try { + const pg15Result = await parser15.parse(sql); + const pg16Result = await parser16.parse(sql); + + const pg15AConsts = findAConstNodes(pg15Result); + const pg16AConsts = findAConstNodes(pg16Result); + + console.log("PG15 A_Const nodes:", JSON.stringify(pg15AConsts, null, 2)); + console.log("PG16 A_Const nodes:", JSON.stringify(pg16AConsts, null, 2)); + + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, 15, 16); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + const transformedAConsts = findAConstNodes(astToTransform); + console.log("Transformed A_Const nodes:", JSON.stringify(transformedAConsts, null, 2)); + + } catch (error) { + console.error("Error:", error.message); + } + } +} + +function findAConstNodes(obj, path = []) { + const results = []; + + if (typeof obj !== 'object' || obj === null) { + return results; + } + + if (obj.A_Const) { + results.push({ + path: path.concat(['A_Const']), + node: obj.A_Const + }); + } + + for (const [key, value] of Object.entries(obj)) { + if (typeof value === 'object' && value !== null) { + results.push(...findAConstNodes(value, path.concat([key]))); + } + } + + return results; +} + +debugAConstTransformation(); diff --git a/packages/transform/debug_alter_table.js b/packages/transform/debug_alter_table.js new file mode 100644 index 00000000..e260cbee --- /dev/null +++ b/packages/transform/debug_alter_table.js @@ -0,0 +1,53 @@ +const { Parser } = require('@pgsql/parser'); +const { ASTTransformer } = require('./dist/transformer'); + +async function debugAlterTableTransformation() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + const transformer = new ASTTransformer(); + + const sql = "ALTER TABLE tmp ADD COLUMN j abstime[]"; + + console.log("=== DEBUGGING ALTER TABLE TRANSFORMATION ==="); + console.log("SQL:", sql); + + try { + const pg15Result = await parser15.parse(sql); + console.log("\n=== PG15 PARSED RESULT ==="); + console.log(JSON.stringify(pg15Result, null, 2)); + + const pg16Result = await parser16.parse(sql); + console.log("\n=== PG16 PARSED RESULT ==="); + console.log(JSON.stringify(pg16Result, null, 2)); + + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, 15, 16); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + astToTransform.version = pg16Result.version; + + console.log("\n=== TRANSFORMED RESULT ==="); + console.log(JSON.stringify(astToTransform, null, 2)); + + // Focus on arrayBounds specifically + const arrayBounds15 = pg15Result.stmts?.[0]?.stmt?.AlterTableStmt?.cmds?.[0]?.AlterTableCmd?.def?.ColumnDef?.typeName?.arrayBounds; + const arrayBounds16 = pg16Result.stmts?.[0]?.stmt?.AlterTableStmt?.cmds?.[0]?.AlterTableCmd?.def?.ColumnDef?.typeName?.arrayBounds; + const arrayBoundsTransformed = astToTransform.stmts?.[0]?.stmt?.AlterTableStmt?.cmds?.[0]?.AlterTableCmd?.def?.ColumnDef?.typeName?.arrayBounds; + + console.log("\n=== ARRAY BOUNDS COMPARISON ==="); + console.log("PG15 arrayBounds:", JSON.stringify(arrayBounds15, null, 2)); + console.log("PG16 arrayBounds:", JSON.stringify(arrayBounds16, null, 2)); + console.log("Transformed arrayBounds:", JSON.stringify(arrayBoundsTransformed, null, 2)); + + } catch (error) { + console.error("Error:", error.message); + } +} + +debugAlterTableTransformation(); diff --git a/packages/transform/debug_alternative_approach.js b/packages/transform/debug_alternative_approach.js new file mode 100644 index 00000000..743e45d1 --- /dev/null +++ b/packages/transform/debug_alternative_approach.js @@ -0,0 +1,78 @@ +const { Parser } = require('@pgsql/parser'); + +async function exploreAlternativeApproaches() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + + const testCases = [ + { sql: "insert into atacc2 (test2) values (-3)", type: "negative" }, + { sql: "insert into atacc2 (test2) values (0)", type: "zero" }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= -1)", type: "negative" }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)", type: "zero" } + ]; + + console.log("=== EXPLORING ALTERNATIVE APPROACHES ==="); + + for (const testCase of testCases) { + console.log(`\n=== ${testCase.type.toUpperCase()}: ${testCase.sql} ===`); + + try { + const pg15Result = await parser15.parse(testCase.sql); + const pg16Result = await parser16.parse(testCase.sql); + + const pg15AConst = findAConstWithContext(pg15Result); + const pg16AConst = findAConstWithContext(pg16Result); + + if (pg15AConst && pg16AConst) { + console.log("PG15 A_Const context:", JSON.stringify({ + ival: pg15AConst.node.ival, + location: pg15AConst.node.location, + parentPath: pg15AConst.path + }, null, 2)); + + console.log("PG16 A_Const context:", JSON.stringify({ + ival: pg16AConst.node.ival, + location: pg16AConst.node.location, + parentPath: pg16AConst.path + }, null, 2)); + + const shouldTransform = JSON.stringify(pg15AConst.node.ival) !== JSON.stringify(pg16AConst.node.ival); + console.log("Should transform:", shouldTransform); + + if (shouldTransform) { + console.log("PATTERN: Empty ival in PG15 should become nested in PG16"); + } else { + console.log("PATTERN: Empty ival should remain empty"); + } + } + + } catch (error) { + console.error("Error:", error.message); + } + } + + console.log("\n=== POTENTIAL SOLUTIONS ==="); + console.log("1. Parse-time detection: Check if original SQL contains negative number"); + console.log("2. Location-based heuristics: Use location differences to detect patterns"); + console.log("3. Dual-parse approach: Parse with both PG15 and PG16 to compare expected results"); + console.log("4. SQL regex analysis: Extract numeric values from original SQL before parsing"); +} + +function findAConstWithContext(obj, path = []) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) { + return { node: obj.A_Const, path: [...path, 'A_Const'] }; + } + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstWithContext(obj[key], [...path, key]); + if (result) return result; + } + } + + return null; +} + +exploreAlternativeApproaches(); diff --git a/packages/transform/debug_ci_failure.js b/packages/transform/debug_ci_failure.js new file mode 100644 index 00000000..3ef84356 --- /dev/null +++ b/packages/transform/debug_ci_failure.js @@ -0,0 +1,93 @@ +const { Parser } = require('@pgsql/parser'); +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +class DebugTransformer extends V15ToV16Transformer { + A_Const(node, context) { + console.log('=== A_Const Debug ==='); + console.log('Input node:', JSON.stringify(node, null, 2)); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + + const result = super.A_Const(node, context); + console.log('A_Const result:', JSON.stringify(result, null, 2)); + console.log('====================='); + + return result; + } + + Integer(node, context) { + console.log('=== Integer Debug ==='); + console.log('Input node:', JSON.stringify(node, null, 2)); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + console.log('Is empty?', Object.keys(node).length === 0); + console.log('Has A_Const parent?', context.parentNodeTypes.includes('A_Const')); + + const result = super.Integer(node, context); + console.log('Integer result:', JSON.stringify(result, null, 2)); + console.log('==================='); + + return result; + } +} + +async function debugCIFailure() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + const transformer = new DebugTransformer(); + + const sql = "insert into atacc2 (test2) values (-3)"; + + console.log("=== DEBUGGING CI FAILURE ==="); + console.log("SQL:", sql); + + try { + const pg15Result = await parser15.parse(sql); + const pg16Result = await parser16.parse(sql); + + console.log("\n=== PG15 A_Const ival ==="); + const pg15AConst = findAConstInInsert(pg15Result); + console.log(JSON.stringify(pg15AConst?.ival, null, 2)); + + console.log("\n=== PG16 A_Const ival ==="); + const pg16AConst = findAConstInInsert(pg16Result); + console.log(JSON.stringify(pg16AConst?.ival, null, 2)); + + console.log("\n=== STARTING TRANSFORMATION ==="); + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, { parentNodeTypes: [] }); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + console.log("\n=== TRANSFORMED A_Const ival ==="); + const transformedAConst = findAConstInInsert(astToTransform); + console.log(JSON.stringify(transformedAConst?.ival, null, 2)); + + console.log("\n=== COMPARISON ==="); + console.log("PG15 produces:", JSON.stringify(pg15AConst?.ival)); + console.log("PG16 expects:", JSON.stringify(pg16AConst?.ival)); + console.log("My transform produces:", JSON.stringify(transformedAConst?.ival)); + console.log("Match PG16?", JSON.stringify(transformedAConst?.ival) === JSON.stringify(pg16AConst?.ival)); + + } catch (error) { + console.error("Error:", error.message); + } +} + +function findAConstInInsert(obj) { + if (!obj || typeof obj !== 'object') return null; + + try { + return obj.stmts[0].stmt.InsertStmt.selectStmt.SelectStmt.valuesLists[0].List.items[0].A_Const; + } catch (e) { + return null; + } +} + +debugCIFailure(); diff --git a/packages/transform/debug_context.js b/packages/transform/debug_context.js new file mode 100644 index 00000000..df4cac71 --- /dev/null +++ b/packages/transform/debug_context.js @@ -0,0 +1,50 @@ +const { Parser } = require('@pgsql/parser'); +const { ASTTransformer } = require('./dist/transformer'); + +class DebugTransformer extends ASTTransformer { + A_Const(node, context) { + console.log('=== A_Const Context Debug ==='); + console.log('Node:', JSON.stringify(node, null, 2)); + console.log('Context parentNodeTypes:', context.parentNodeTypes); + console.log('Context path:', context.path); + console.log('================================'); + + return super.A_Const(node, context); + } +} + +async function debugContext() { + const parser15 = new Parser(15); + const transformer = new DebugTransformer(); + + const testCases = [ + "insert into atacc2 (test2) values (-3)", + "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)" + ]; + + console.log("=== DEBUGGING A_CONST CONTEXT ==="); + + for (const sql of testCases) { + console.log(`\n=== SQL: ${sql} ===`); + + try { + const pg15Result = await parser15.parse(sql); + + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, 15, 16); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + } catch (error) { + console.error("Error:", error.message); + } + } +} + +debugContext(); diff --git a/packages/transform/debug_context_analysis.js b/packages/transform/debug_context_analysis.js new file mode 100644 index 00000000..a591a0e3 --- /dev/null +++ b/packages/transform/debug_context_analysis.js @@ -0,0 +1,94 @@ +const { Parser } = require('@pgsql/parser'); +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +class ContextAnalysisTransformer extends V15ToV16Transformer { + A_Const(node, context) { + console.log('=== A_Const Context Analysis ==='); + console.log('Input node:', JSON.stringify(node, null, 2)); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + console.log('Context keys:', Object.keys(context)); + + const hasInsertContext = context.parentNodeTypes.includes('InsertStmt'); + const hasConstraintContext = context.parentNodeTypes.includes('Constraint'); + const hasExprContext = context.parentNodeTypes.includes('A_Expr'); + + console.log('Insert context:', hasInsertContext); + console.log('Constraint context:', hasConstraintContext); + console.log('Expression context:', hasExprContext); + + const result = super.A_Const(node, context); + console.log('A_Const result:', JSON.stringify(result, null, 2)); + console.log('================================'); + + return result; + } +} + +async function analyzeContext() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + const transformer = new ContextAnalysisTransformer(); + + const testCases = [ + { + name: "Negative integer in INSERT", + sql: "insert into atacc2 (test2) values (-3)" + }, + { + name: "Zero in constraint", + sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)" + }, + { + name: "Positive integer", + sql: "insert into atacc2 (test2) values (5)" + } + ]; + + console.log("=== CONTEXT ANALYSIS FOR A_CONST TRANSFORMATION ==="); + + for (const testCase of testCases) { + console.log(`\n=== ${testCase.name}: ${testCase.sql} ===`); + + try { + const pg15Result = await parser15.parse(testCase.sql); + const pg16Result = await parser16.parse(testCase.sql); + + console.log("\n--- PG16 Expected Result ---"); + const pg16AConst = findAConstInAST(pg16Result); + console.log("PG16 A_Const ival:", JSON.stringify(pg16AConst?.ival)); + + console.log("\n--- Transformation Analysis ---"); + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, { parentNodeTypes: [] }); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + } catch (error) { + console.error("Error:", error.message); + } + } +} + +function findAConstInAST(obj) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) return obj.A_Const; + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstInAST(obj[key]); + if (result) return result; + } + } + + return null; +} + +analyzeContext(); diff --git a/packages/transform/debug_context_detailed.js b/packages/transform/debug_context_detailed.js new file mode 100644 index 00000000..06b59128 --- /dev/null +++ b/packages/transform/debug_context_detailed.js @@ -0,0 +1,67 @@ +const { Parser } = require('@pgsql/parser'); +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +class DebugTransformer extends V15ToV16Transformer { + Integer(node, context) { + console.log('=== Integer method called ==='); + console.log('Node:', JSON.stringify(node, null, 2)); + console.log('Context parentNodeTypes:', context.parentNodeTypes); + console.log('Context path:', context.path); + console.log('Object.keys(node).length:', Object.keys(node).length); + console.log('Is empty?', Object.keys(node).length === 0); + console.log('Has TypeName parent?', context.parentNodeTypes.includes('TypeName')); + console.log('Has A_Const parent?', context.parentNodeTypes.includes('A_Const')); + + const result = super.Integer(node, context); + console.log('Result:', JSON.stringify(result, null, 2)); + console.log('================================'); + + return result; + } + + A_Const(node, context) { + console.log('=== A_Const method called ==='); + console.log('Node:', JSON.stringify(node, null, 2)); + console.log('Context parentNodeTypes:', context.parentNodeTypes); + console.log('Context path:', context.path); + + const result = super.A_Const(node, context); + console.log('A_Const result:', JSON.stringify(result, null, 2)); + console.log('================================'); + + return result; + } +} + +async function debugContextDetailed() { + const parser15 = new Parser(15); + const transformer = new DebugTransformer(); + + const sql = "insert into atacc2 (test2) values (-3)"; + + console.log("=== DEBUGGING DETAILED CONTEXT ==="); + console.log("SQL:", sql); + + try { + const pg15Result = await parser15.parse(sql); + + console.log("\n=== STARTING TRANSFORMATION ==="); + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, { parentNodeTypes: [] }); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + console.log("\n=== TRANSFORMATION COMPLETE ==="); + + } catch (error) { + console.error("Error:", error.message); + } +} + +debugContextDetailed(); diff --git a/packages/transform/debug_dual_parse_approach.js b/packages/transform/debug_dual_parse_approach.js new file mode 100644 index 00000000..d657b7c7 --- /dev/null +++ b/packages/transform/debug_dual_parse_approach.js @@ -0,0 +1,98 @@ +const { Parser } = require('@pgsql/parser'); + +async function exploreDualParseApproach() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + + const testCases = [ + { sql: "insert into atacc2 (test2) values (-3)", expected: "negative" }, + { sql: "insert into atacc2 (test2) values (0)", expected: "zero" }, + { sql: "insert into atacc2 (test2) values (5)", expected: "positive" }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= -1)", expected: "negative" }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)", expected: "zero" } + ]; + + console.log("=== DUAL-PARSE APPROACH EXPLORATION ==="); + console.log("Strategy: Parse same SQL with both PG15 and PG16, compare A_Const ival structures"); + console.log("If PG15 has empty {} but PG16 has nested {ival: X}, then transform is needed\n"); + + const transformationRules = []; + + for (const testCase of testCases) { + console.log(`=== ${testCase.expected.toUpperCase()}: ${testCase.sql} ===`); + + try { + const pg15Result = await parser15.parse(testCase.sql); + const pg16Result = await parser16.parse(testCase.sql); + + const pg15AConst = findAConstInAST(pg15Result); + const pg16AConst = findAConstInAST(pg16Result); + + if (pg15AConst && pg16AConst) { + const pg15IsEmpty = pg15AConst.ival && Object.keys(pg15AConst.ival).length === 0; + const pg16HasNested = pg16AConst.ival && typeof pg16AConst.ival.ival === 'number'; + const shouldTransform = pg15IsEmpty && pg16HasNested; + + console.log("PG15 ival:", JSON.stringify(pg15AConst.ival)); + console.log("PG16 ival:", JSON.stringify(pg16AConst.ival)); + console.log("PG15 is empty:", pg15IsEmpty); + console.log("PG16 has nested:", pg16HasNested); + console.log("Should transform:", shouldTransform); + + if (shouldTransform) { + const targetValue = pg16AConst.ival.ival; + console.log(`RULE: Transform empty {} to {ival: ${targetValue}}`); + transformationRules.push({ + sql: testCase.sql, + targetValue: targetValue, + type: testCase.expected + }); + } else { + console.log("RULE: Keep empty {} as is"); + } + + console.log(""); + } + + } catch (error) { + console.error("Error:", error.message); + } + } + + console.log("=== TRANSFORMATION RULES DISCOVERED ==="); + transformationRules.forEach((rule, i) => { + console.log(`${i + 1}. ${rule.type} integers: Transform {} to {ival: ${rule.targetValue}}`); + }); + + console.log("\n=== DUAL-PARSE IMPLEMENTATION STRATEGY ==="); + console.log("1. In A_Const method, when encountering empty ival object:"); + console.log("2. Extract the original SQL from the current transformation context"); + console.log("3. Parse the SQL with both PG15 and PG16"); + console.log("4. Compare the A_Const ival structures"); + console.log("5. If PG16 expects nested structure, transform; otherwise keep empty"); + console.log("6. Cache results to avoid re-parsing the same SQL multiple times"); + + console.log("\n=== FEASIBILITY ASSESSMENT ==="); + console.log("✅ Technically feasible - can access both parsers in transformer"); + console.log("✅ Accurate - directly compares what PG16 expects vs PG15 produces"); + console.log("⚠️ Performance - may be slower due to dual parsing"); + console.log("⚠️ Complexity - need to extract original SQL from transformation context"); + console.log("✅ Reliable - eliminates guesswork about when to transform"); +} + +function findAConstInAST(obj) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) return obj.A_Const; + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstInAST(obj[key]); + if (result) return result; + } + } + + return null; +} + +exploreDualParseApproach(); diff --git a/packages/transform/debug_dual_parse_implementation.js b/packages/transform/debug_dual_parse_implementation.js new file mode 100644 index 00000000..243ec390 --- /dev/null +++ b/packages/transform/debug_dual_parse_implementation.js @@ -0,0 +1,77 @@ +const { Parser } = require('@pgsql/parser'); + +async function testDualParseImplementation() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + + console.log("=== DUAL-PARSE IMPLEMENTATION TEST ==="); + console.log("Testing the approach for detecting when empty ival objects need transformation\n"); + + const testCases = [ + { sql: "insert into atacc2 (test2) values (-3)", expected: "should transform" }, + { sql: "insert into atacc2 (test2) values (0)", expected: "should NOT transform" }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= -1)", expected: "should transform" }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)", expected: "should NOT transform" } + ]; + + for (const testCase of testCases) { + console.log(`=== SQL: ${testCase.sql} ===`); + console.log(`Expected: ${testCase.expected}`); + + try { + const pg15Result = await parser15.parse(testCase.sql); + const pg16Result = await parser16.parse(testCase.sql); + + const pg15AConst = findAConstInAST(pg15Result); + const pg16AConst = findAConstInAST(pg16Result); + + if (pg15AConst && pg16AConst) { + const pg15IsEmpty = pg15AConst.ival && Object.keys(pg15AConst.ival).length === 0; + const pg16HasNested = pg16AConst.ival && typeof pg16AConst.ival.ival === 'number'; + + console.log("PG15 ival:", JSON.stringify(pg15AConst.ival)); + console.log("PG16 ival:", JSON.stringify(pg16AConst.ival)); + console.log("PG15 is empty:", pg15IsEmpty); + console.log("PG16 has nested:", pg16HasNested); + + if (pg15IsEmpty && pg16HasNested) { + console.log(`✅ TRANSFORM NEEDED: {} -> {ival: ${pg16AConst.ival.ival}}`); + } else if (pg15IsEmpty && !pg16HasNested) { + console.log("✅ KEEP EMPTY: {} -> {}"); + } else { + console.log("ℹ️ No transformation needed (not empty ival case)"); + } + + console.log(""); + } + + } catch (error) { + console.error("Error:", error.message); + } + } + + console.log("=== IMPLEMENTATION STRATEGY ==="); + console.log("1. Create helper method shouldTransformEmptyIval(sql) that:"); + console.log(" - Parses SQL with both PG15 and PG16"); + console.log(" - Compares A_Const ival structures"); + console.log(" - Returns transformation target if needed, null otherwise"); + console.log("2. Use this in A_Const method when encountering empty ival objects"); + console.log("3. Cache results to avoid re-parsing same SQL multiple times"); +} + +function findAConstInAST(obj) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) return obj.A_Const; + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstInAST(obj[key]); + if (result) return result; + } + } + + return null; +} + +testDualParseImplementation(); diff --git a/packages/transform/debug_dual_parse_test.js b/packages/transform/debug_dual_parse_test.js new file mode 100644 index 00000000..83a849f4 --- /dev/null +++ b/packages/transform/debug_dual_parse_test.js @@ -0,0 +1,64 @@ +const { Parser } = require('@pgsql/parser'); + +function testDualParseApproach() { + console.log("=== TESTING DUAL-PARSE APPROACH ==="); + + try { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + + console.log("Parsers created successfully"); + + const simpleSQL = "SELECT 1"; + console.log(`Testing simple SQL: ${simpleSQL}`); + + const simple15 = parser15.parse(simpleSQL); + const simple16 = parser16.parse(simpleSQL); + + console.log("Simple PG15 result keys:", Object.keys(simple15)); + console.log("Simple PG16 result keys:", Object.keys(simple16)); + + const testSQL = "INSERT INTO test VALUES (-3)"; + console.log(`\nTesting negative integer SQL: ${testSQL}`); + + const pg15Result = parser15.parse(testSQL); + const pg16Result = parser16.parse(testSQL); + + console.log("PG15 result keys:", Object.keys(pg15Result)); + console.log("PG16 result keys:", Object.keys(pg16Result)); + + if (Object.keys(pg15Result).length > 0 && Object.keys(pg16Result).length > 0) { + console.log("PG15 result:", JSON.stringify(pg15Result, null, 2)); + console.log("PG16 result:", JSON.stringify(pg16Result, null, 2)); + + const pg15AConst = findAConstInAST(pg15Result); + const pg16AConst = findAConstInAST(pg16Result); + + console.log("PG15 A_Const:", JSON.stringify(pg15AConst, null, 2)); + console.log("PG16 A_Const:", JSON.stringify(pg16AConst, null, 2)); + } else { + console.log("❌ FAILED: Parsers returning empty objects"); + } + + } catch (error) { + console.error("❌ ERROR:", error.message); + console.error("Stack:", error.stack); + } +} + +function findAConstInAST(obj) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) return obj.A_Const; + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstInAST(obj[key]); + if (result) return result; + } + } + + return null; +} + +testDualParseApproach(); diff --git a/packages/transform/debug_empty_ival_detection.js b/packages/transform/debug_empty_ival_detection.js new file mode 100644 index 00000000..cb0b4fc1 --- /dev/null +++ b/packages/transform/debug_empty_ival_detection.js @@ -0,0 +1,93 @@ +const { Parser } = require('@pgsql/parser'); +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +async function debugEmptyIvalDetection() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + + console.log("=== EMPTY IVAL DETECTION STRATEGY ==="); + console.log("Goal: Detect when empty {} should become {ival: X} vs remain empty\n"); + + const testCases = [ + { sql: "insert into atacc2 (test2) values (-3)", expected: "transform", desc: "negative integer" }, + { sql: "insert into atacc2 (test2) values (0)", expected: "keep empty", desc: "zero value" }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= -1)", expected: "transform", desc: "negative in constraint" }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)", expected: "keep empty", desc: "zero in constraint" } + ]; + + const transformationRules = []; + + for (const testCase of testCases) { + console.log(`=== ${testCase.desc.toUpperCase()}: ${testCase.sql} ===`); + + try { + const pg15Result = await parser15.parse(testCase.sql); + const pg16Result = await parser16.parse(testCase.sql); + + const pg15AConst = findAConstInAST(pg15Result); + const pg16AConst = findAConstInAST(pg16Result); + + if (pg15AConst && pg16AConst) { + const pg15IsEmpty = pg15AConst.ival && Object.keys(pg15AConst.ival).length === 0; + const pg16HasNested = pg16AConst.ival && typeof pg16AConst.ival.ival === 'number'; + + console.log("PG15 ival:", JSON.stringify(pg15AConst.ival)); + console.log("PG16 ival:", JSON.stringify(pg16AConst.ival)); + console.log("Should transform:", pg15IsEmpty && pg16HasNested); + + if (pg15IsEmpty && pg16HasNested) { + const targetValue = pg16AConst.ival.ival; + transformationRules.push({ + sql: testCase.sql, + targetValue: targetValue, + pattern: `Transform {} to {ival: ${targetValue}}` + }); + console.log(`✅ RULE: ${transformationRules[transformationRules.length - 1].pattern}`); + } else if (pg15IsEmpty && !pg16HasNested) { + console.log("✅ RULE: Keep {} as empty"); + } + + console.log(""); + } + + } catch (error) { + console.error("Error:", error.message); + } + } + + console.log("=== IMPLEMENTATION STRATEGY ==="); + console.log("Since we can't easily implement async dual-parse in transformer:"); + console.log("1. Create a synchronous helper that uses SQL pattern matching"); + console.log("2. Extract numeric patterns from context or SQL fragments"); + console.log("3. Use heuristics based on common negative integer patterns"); + console.log("4. Implement conservative transformation that only handles clear cases"); + + console.log("\n=== DISCOVERED TRANSFORMATION RULES ==="); + transformationRules.forEach((rule, i) => { + console.log(`${i + 1}. ${rule.pattern} (from: ${rule.sql.substring(0, 50)}...)`); + }); + + console.log("\n=== NEXT STEPS ==="); + console.log("Implement targeted A_Const fix that:"); + console.log("- Detects empty ival objects"); + console.log("- Uses context clues to determine if transformation needed"); + console.log("- Only transforms when confident it's a negative integer case"); + console.log("- Preserves zero values as empty objects"); +} + +function findAConstInAST(obj) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) return obj.A_Const; + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstInAST(obj[key]); + if (result) return result; + } + } + + return null; +} + +debugEmptyIvalDetection(); diff --git a/packages/transform/debug_insert_negative.js b/packages/transform/debug_insert_negative.js new file mode 100644 index 00000000..516d5f51 --- /dev/null +++ b/packages/transform/debug_insert_negative.js @@ -0,0 +1,68 @@ +const { Parser } = require('@pgsql/parser'); +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +async function debugInsertNegative() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + const transformer = new V15ToV16Transformer(); + + const sql = "insert into atacc2 (test2) values (-3)"; + + console.log("=== DEBUGGING INSERT NEGATIVE INTEGER ==="); + console.log("SQL:", sql); + + try { + const pg15Result = await parser15.parse(sql); + console.log("\n=== PG15 PARSED RESULT ==="); + console.log(JSON.stringify(pg15Result, null, 2)); + + const pg16Result = await parser16.parse(sql); + console.log("\n=== PG16 PARSED RESULT ==="); + console.log(JSON.stringify(pg16Result, null, 2)); + + const pg15AConst = findAConstInInsert(pg15Result); + const pg16AConst = findAConstInInsert(pg16Result); + + console.log("\n=== PG15 A_Const ==="); + console.log(JSON.stringify(pg15AConst, null, 2)); + + console.log("\n=== PG16 A_Const ==="); + console.log(JSON.stringify(pg16AConst, null, 2)); + + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, { parentNodeTypes: [] }); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + astToTransform.version = pg16Result.version; + + const transformedAConst = findAConstInInsert(astToTransform); + console.log("\n=== TRANSFORMED A_Const ==="); + console.log(JSON.stringify(transformedAConst, null, 2)); + + console.log("\n=== COMPARISON ==="); + console.log("PG15 ival:", JSON.stringify(pg15AConst?.ival)); + console.log("PG16 ival:", JSON.stringify(pg16AConst?.ival)); + console.log("Transformed ival:", JSON.stringify(transformedAConst?.ival)); + + } catch (error) { + console.error("Error:", error.message); + } +} + +function findAConstInInsert(obj) { + if (!obj || typeof obj !== 'object') return null; + + try { + return obj.stmts[0].stmt.InsertStmt.selectStmt.SelectStmt.valuesLists[0].List.items[0].A_Const; + } catch (e) { + return null; + } +} + +debugInsertNegative(); diff --git a/packages/transform/debug_ival_contexts.js b/packages/transform/debug_ival_contexts.js new file mode 100644 index 00000000..ecdbb3f3 --- /dev/null +++ b/packages/transform/debug_ival_contexts.js @@ -0,0 +1,98 @@ +const { Parser } = require('@pgsql/parser'); +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +class IvalContextAnalyzer extends V15ToV16Transformer { + A_Const(node, context) { + if (node.ival !== undefined && typeof node.ival === 'object' && Object.keys(node.ival).length === 0) { + console.log('=== EMPTY IVAL CONTEXT ==='); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + console.log('Full node:', JSON.stringify(node, null, 2)); + console.log('========================'); + } + + return super.A_Const(node, context); + } +} + +async function analyzeIvalContexts() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + const analyzer = new IvalContextAnalyzer(); + + const testCases = [ + { + name: "Negative integer in INSERT", + sql: "insert into atacc2 (test2) values (-3)" + }, + { + name: "Zero in constraint", + sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)" + }, + { + name: "Positive integer", + sql: "insert into atacc2 (test2) values (5)" + }, + { + name: "Zero in INSERT", + sql: "insert into atacc2 (test2) values (0)" + }, + { + name: "Negative in constraint", + sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= -1)" + } + ]; + + console.log("=== ANALYZING EMPTY IVAL CONTEXTS ==="); + + for (const testCase of testCases) { + console.log(`\n=== ${testCase.name}: ${testCase.sql} ===`); + + try { + const pg15Result = await parser15.parse(testCase.sql); + const pg16Result = await parser16.parse(testCase.sql); + + console.log("\n--- PG15 vs PG16 Comparison ---"); + const pg15AConst = findAConstInAST(pg15Result); + const pg16AConst = findAConstInAST(pg16Result); + + if (pg15AConst && pg16AConst) { + console.log("PG15 ival:", JSON.stringify(pg15AConst.ival)); + console.log("PG16 ival:", JSON.stringify(pg16AConst.ival)); + console.log("Should transform?", JSON.stringify(pg15AConst.ival) !== JSON.stringify(pg16AConst.ival)); + } + + console.log("\n--- Transformation Analysis ---"); + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = analyzer.transform(stmtWrapper.stmt, { parentNodeTypes: [] }); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + } catch (error) { + console.error("Error:", error.message); + } + } +} + +function findAConstInAST(obj) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) return obj.A_Const; + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstInAST(obj[key]); + if (result) return result; + } + } + + return null; +} + +analyzeIvalContexts(); diff --git a/packages/transform/debug_sql_parsing.js b/packages/transform/debug_sql_parsing.js new file mode 100644 index 00000000..bea6b8c5 --- /dev/null +++ b/packages/transform/debug_sql_parsing.js @@ -0,0 +1,58 @@ +const { Parser } = require('@pgsql/parser'); + +async function debugSQLParsing() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + + const testCases = [ + "insert into atacc2 (test2) values (-3)", + "insert into atacc2 (test2) values (3)", + "insert into atacc2 (test2) values (0)", + "ALTER TABLE tmp ADD COLUMN j abstime[]" + ]; + + console.log("=== DEBUGGING SQL PARSING PATTERNS ==="); + + for (const sql of testCases) { + console.log(`\n=== SQL: ${sql} ===`); + + try { + const pg15Result = await parser15.parse(sql); + const pg16Result = await parser16.parse(sql); + + const pg15Integers = findAllIntegers(pg15Result); + const pg16Integers = findAllIntegers(pg16Result); + + console.log("PG15 Integer nodes:", JSON.stringify(pg15Integers, null, 2)); + console.log("PG16 Integer nodes:", JSON.stringify(pg16Integers, null, 2)); + + } catch (error) { + console.error("Error:", error.message); + } + } +} + +function findAllIntegers(obj, path = []) { + const results = []; + + if (typeof obj !== 'object' || obj === null) { + return results; + } + + if (obj.Integer !== undefined) { + results.push({ + path: path.concat(['Integer']), + node: obj.Integer + }); + } + + for (const [key, value] of Object.entries(obj)) { + if (typeof value === 'object' && value !== null) { + results.push(...findAllIntegers(value, path.concat([key]))); + } + } + + return results; +} + +debugSQLParsing(); diff --git a/packages/transform/debug_sql_value_analysis.js b/packages/transform/debug_sql_value_analysis.js new file mode 100644 index 00000000..f121da97 --- /dev/null +++ b/packages/transform/debug_sql_value_analysis.js @@ -0,0 +1,65 @@ +const { Parser } = require('@pgsql/parser'); + +async function analyzeSQLValues() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + + const testCases = [ + { sql: "insert into atacc2 (test2) values (-3)", expectedValue: -3 }, + { sql: "insert into atacc2 (test2) values (0)", expectedValue: 0 }, + { sql: "insert into atacc2 (test2) values (5)", expectedValue: 5 }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)", expectedValue: 0 }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= -1)", expectedValue: -1 }, + { sql: "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= -5)", expectedValue: -5 }, + ]; + + console.log("=== SQL VALUE ANALYSIS ==="); + + for (const testCase of testCases) { + console.log(`\n=== SQL: ${testCase.sql} ===`); + console.log(`Expected value: ${testCase.expectedValue}`); + + try { + const pg15Result = await parser15.parse(testCase.sql); + const pg16Result = await parser16.parse(testCase.sql); + + const pg15AConst = findAConstInAST(pg15Result); + const pg16AConst = findAConstInAST(pg16Result); + + console.log("PG15 ival:", JSON.stringify(pg15AConst?.ival)); + console.log("PG16 ival:", JSON.stringify(pg16AConst?.ival)); + + const pg15IsEmpty = pg15AConst?.ival && Object.keys(pg15AConst.ival).length === 0; + const pg16HasValue = pg16AConst?.ival && typeof pg16AConst.ival.ival === 'number'; + + console.log("PG15 has empty ival:", pg15IsEmpty); + console.log("PG16 has ival value:", pg16HasValue); + console.log("Should transform:", pg15IsEmpty && pg16HasValue); + + if (pg16HasValue) { + console.log("PG16 actual value:", pg16AConst.ival.ival); + console.log("Matches expected:", pg16AConst.ival.ival === testCase.expectedValue); + } + + } catch (error) { + console.error("Error:", error.message); + } + } +} + +function findAConstInAST(obj) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) return obj.A_Const; + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstInAST(obj[key]); + if (result) return result; + } + } + + return null; +} + +analyzeSQLValues(); diff --git a/packages/transform/debug_targeted_fix.js b/packages/transform/debug_targeted_fix.js new file mode 100644 index 00000000..a6baad23 --- /dev/null +++ b/packages/transform/debug_targeted_fix.js @@ -0,0 +1,41 @@ +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +function debugTargetedFix() { + console.log("=== TARGETED A_CONST FIX APPROACH ==="); + console.log("Strategy: Only transform empty ival objects in specific contexts where confident it's negative\n"); + + const transformer = new V15ToV16Transformer(); + + const testNode = { + A_Const: { + ival: {}, // Empty object that PG15 produces for negative integers + location: 63 + } + }; + + console.log("=== TEST CASE: Empty ival object ==="); + console.log("Input node:", JSON.stringify(testNode, null, 2)); + + const context = { parentNodeTypes: ['TypeName', 'ColumnDef', 'CreateStmt'] }; + const result = transformer.transform(testNode, context); + + console.log("Transformed result:", JSON.stringify(result, null, 2)); + console.log("Expected PG16 result: { A_Const: { ival: { ival: -3 }, location: 63 } }"); + + console.log("\n=== ANALYSIS ==="); + const hasEmptyIval = result.A_Const && result.A_Const.ival && + typeof result.A_Const.ival === 'object' && + Object.keys(result.A_Const.ival).length === 0; + + console.log("Result has empty ival:", hasEmptyIval); + console.log("Transformation needed:", hasEmptyIval ? "YES" : "NO"); + + if (hasEmptyIval) { + console.log("\n=== PROPOSED FIX ==="); + console.log("Detect empty ival objects in A_Const and transform to nested structure"); + console.log("Use context clues or heuristics to determine appropriate negative value"); + console.log("Conservative approach: only transform when confident it's a negative integer case"); + } +} + +debugTargetedFix(); diff --git a/packages/transform/debug_transformation_flow.js b/packages/transform/debug_transformation_flow.js new file mode 100644 index 00000000..173b7224 --- /dev/null +++ b/packages/transform/debug_transformation_flow.js @@ -0,0 +1,66 @@ +const { Parser } = require('@pgsql/parser'); +const { ASTTransformer } = require('./dist/transformer'); + +class DebugTransformer extends ASTTransformer { + transform(node, fromVersion, toVersion) { + console.log('=== Transform called ==='); + console.log('Node type:', this.getNodeType(node)); + console.log('Node data:', JSON.stringify(this.getNodeData(node), null, 2)); + console.log('========================'); + + return super.transform(node, fromVersion, toVersion); + } + + A_Const(node, context) { + console.log('=== A_Const called ==='); + console.log('Node:', JSON.stringify(node, null, 2)); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + console.log('========================'); + + return super.A_Const(node, context); + } + + Integer(node, context) { + console.log('=== Integer called ==='); + console.log('Node:', JSON.stringify(node, null, 2)); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + console.log('========================'); + + return super.Integer(node, context); + } +} + +async function debugTransformationFlow() { + const parser15 = new Parser(15); + const transformer = new DebugTransformer(); + + const sql = "insert into atacc2 (test2) values (-3)"; + + console.log("=== DEBUGGING TRANSFORMATION FLOW ==="); + console.log("SQL:", sql); + + try { + const pg15Result = await parser15.parse(sql); + + console.log("\n=== STARTING TRANSFORMATION ==="); + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, 15, 16); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + console.log("\n=== TRANSFORMATION COMPLETE ==="); + + } catch (error) { + console.error("Error:", error.message); + } +} + +debugTransformationFlow(); diff --git a/packages/transform/debug_transformation_flow_detailed.js b/packages/transform/debug_transformation_flow_detailed.js new file mode 100644 index 00000000..b5f07965 --- /dev/null +++ b/packages/transform/debug_transformation_flow_detailed.js @@ -0,0 +1,108 @@ +const { Parser } = require('@pgsql/parser'); +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +class FlowAnalysisTransformer extends V15ToV16Transformer { + transform(node, context) { + if (node && typeof node === 'object') { + const nodeType = this.getNodeType(node); + if (nodeType === 'Integer' || nodeType === 'A_Const') { + console.log(`=== TRANSFORM FLOW: ${nodeType} ===`); + console.log('Input node:', JSON.stringify(node, null, 2)); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + console.log('Is empty object?', Object.keys(node).length === 0); + + const result = super.transform(node, context); + console.log('Transform result:', JSON.stringify(result, null, 2)); + console.log('==============================='); + return result; + } + } + return super.transform(node, context); + } + + A_Const(node, context) { + console.log('=== A_CONST METHOD ==='); + console.log('Input node:', JSON.stringify(node, null, 2)); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + + const result = super.A_Const(node, context); + console.log('A_Const result:', JSON.stringify(result, null, 2)); + console.log('==================='); + + return result; + } + + Integer(node, context) { + console.log('=== INTEGER METHOD ==='); + console.log('Input node:', JSON.stringify(node, null, 2)); + console.log('Context path:', context.path); + console.log('Parent types:', context.parentNodeTypes); + console.log('Is empty?', Object.keys(node).length === 0); + + const result = super.Integer(node, context); + console.log('Integer result:', JSON.stringify(result, null, 2)); + console.log('==================='); + + return result; + } +} + +async function analyzeTransformationFlow() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + const transformer = new FlowAnalysisTransformer(); + + const sql = "insert into atacc2 (test2) values (-3)"; + + console.log("=== DETAILED TRANSFORMATION FLOW ANALYSIS ==="); + console.log("SQL:", sql); + + try { + const pg15Result = await parser15.parse(sql); + const pg16Result = await parser16.parse(sql); + + console.log("\n=== PG15 A_Const ival ==="); + const pg15AConst = findAConstInInsert(pg15Result); + console.log(JSON.stringify(pg15AConst?.ival, null, 2)); + + console.log("\n=== PG16 A_Const ival ==="); + const pg16AConst = findAConstInInsert(pg16Result); + console.log(JSON.stringify(pg16AConst?.ival, null, 2)); + + console.log("\n=== STARTING TRANSFORMATION ==="); + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, { parentNodeTypes: [] }); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + console.log("\n=== FINAL COMPARISON ==="); + const transformedAConst = findAConstInInsert(astToTransform); + console.log("PG15 produces:", JSON.stringify(pg15AConst?.ival)); + console.log("PG16 expects:", JSON.stringify(pg16AConst?.ival)); + console.log("My transform produces:", JSON.stringify(transformedAConst?.ival)); + console.log("Match PG16?", JSON.stringify(transformedAConst?.ival) === JSON.stringify(pg16AConst?.ival)); + + } catch (error) { + console.error("Error:", error.message); + } +} + +function findAConstInInsert(obj) { + if (!obj || typeof obj !== 'object') return null; + + try { + return obj.stmts[0].stmt.InsertStmt.selectStmt.SelectStmt.valuesLists[0].List.items[0].A_Const; + } catch (e) { + return null; + } +} + +analyzeTransformationFlow(); diff --git a/packages/transform/debug_zero_vs_negative.js b/packages/transform/debug_zero_vs_negative.js new file mode 100644 index 00000000..9ebe873f --- /dev/null +++ b/packages/transform/debug_zero_vs_negative.js @@ -0,0 +1,66 @@ +const { Parser } = require('@pgsql/parser'); +const { V15ToV16Transformer } = require('./dist/transformers/v15-to-v16'); + +async function debugZeroVsNegative() { + const parser15 = new Parser(15); + const parser16 = new Parser(16); + const transformer = new V15ToV16Transformer(); + + const testCases = [ + "insert into atacc2 (test2) values (-3)", // negative integer + "ALTER TABLE onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0)" // zero + ]; + + console.log("=== DEBUGGING ZERO VS NEGATIVE INTEGER ==="); + + for (const sql of testCases) { + console.log(`\n=== SQL: ${sql} ===`); + + try { + const pg15Result = await parser15.parse(sql); + const pg16Result = await parser16.parse(sql); + + const pg15AConst = findAConstInAST(pg15Result); + const pg16AConst = findAConstInAST(pg16Result); + + console.log("PG15 A_Const ival:", JSON.stringify(pg15AConst?.ival)); + console.log("PG16 A_Const ival:", JSON.stringify(pg16AConst?.ival)); + + const astToTransform = JSON.parse(JSON.stringify(pg15Result)); + if (astToTransform.stmts && Array.isArray(astToTransform.stmts)) { + astToTransform.stmts = astToTransform.stmts.map((stmtWrapper) => { + if (stmtWrapper.stmt) { + const transformedStmt = transformer.transform(stmtWrapper.stmt, { parentNodeTypes: [] }); + return { ...stmtWrapper, stmt: transformedStmt }; + } + return stmtWrapper; + }); + } + + const transformedAConst = findAConstInAST(astToTransform); + console.log("Transformed ival:", JSON.stringify(transformedAConst?.ival)); + + console.log("Should transform?", pg16AConst?.ival && Object.keys(pg16AConst.ival).length > 0 ? "YES" : "NO"); + + } catch (error) { + console.error("Error:", error.message); + } + } +} + +function findAConstInAST(obj) { + if (!obj || typeof obj !== 'object') return null; + + if (obj.A_Const) return obj.A_Const; + + for (const key in obj) { + if (typeof obj[key] === 'object') { + const result = findAConstInAST(obj[key]); + if (result) return result; + } + } + + return null; +} + +debugZeroVsNegative(); diff --git a/packages/transform/src/transformers/v15-to-v16.ts b/packages/transform/src/transformers/v15-to-v16.ts index 26ccc23e..6df37e3e 100644 --- a/packages/transform/src/transformers/v15-to-v16.ts +++ b/packages/transform/src/transformers/v15-to-v16.ts @@ -1,12 +1,16 @@ import * as PG15 from '../15/types'; import { TransformerContext } from './context'; +import { Parser } from '@pgsql/parser'; /** * V15 to V16 AST Transformer * Transforms PostgreSQL v15 AST nodes to v16 format */ export class V15ToV16Transformer { - + + + + transform(node: PG15.Node, context: TransformerContext = { parentNodeTypes: [] }): any { if (node == null) { return null; @@ -20,6 +24,10 @@ export class V15ToV16Transformer { return node; } + if (Array.isArray(node)) { + return node.map(item => this.transform(item, context)); + } + try { return this.visit(node, context); } catch (error) { @@ -30,31 +38,36 @@ export class V15ToV16Transformer { visit(node: PG15.Node, context: TransformerContext = { parentNodeTypes: [] }): any { const nodeType = this.getNodeType(node); - + // Handle empty objects if (!nodeType) { return {}; } - + const nodeData = this.getNodeData(node); const methodName = nodeType as keyof this; if (typeof this[methodName] === 'function') { const childContext: TransformerContext = { ...context, - parentNodeTypes: [...context.parentNodeTypes, nodeType] + parentNodeTypes: [...(context.parentNodeTypes || []), nodeType] }; - const result = (this[methodName] as any)(nodeData, childContext); - - return result; + return (this[methodName] as any)(nodeData, childContext); } - + // If no specific method, return the node as-is return node; } getNodeType(node: PG15.Node): any { - return Object.keys(node)[0]; + const keys = Object.keys(node); + + // Handle parse result structure with version and stmts + if (keys.length === 2 && keys.includes('version') && keys.includes('stmts')) { + return 'ParseResult'; + } + + return keys[0]; } getNodeData(node: PG15.Node): any { @@ -66,7 +79,7 @@ export class V15ToV16Transformer { } ParseResult(node: PG15.ParseResult, context: TransformerContext): any { - + if (node && typeof node === 'object' && 'version' in node && 'stmts' in node) { return { version: 160000, // PG16 version @@ -86,7 +99,21 @@ export class V15ToV16Transformer { } RawStmt(node: PG15.RawStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.stmt !== undefined) { + result.stmt = this.transform(node.stmt as any, context); + } + + if (node.stmt_location !== undefined) { + result.stmt_location = node.stmt_location; + } + + if (node.stmt_len !== undefined) { + result.stmt_len = node.stmt_len; + } + + return { RawStmt: result }; } SelectStmt(node: PG15.SelectStmt, context: TransformerContext): any { @@ -324,7 +351,23 @@ export class V15ToV16Transformer { } WithClause(node: PG15.WithClause, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.ctes !== undefined) { + result.ctes = Array.isArray(node.ctes) + ? node.ctes.map((item: any) => this.transform(item as any, context)) + : this.transform(node.ctes as any, context); + } + + if (node.recursive !== undefined) { + result.recursive = node.recursive; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { WithClause: result }; } ResTarget(node: PG15.ResTarget, context: TransformerContext): any { @@ -428,32 +471,79 @@ export class V15ToV16Transformer { } FuncExpr(node: PG15.FuncExpr, context: TransformerContext): any { - return node; - } - - A_Const(node: PG15.A_Const, context: TransformerContext): any { const result: any = {}; - if (node.sval !== undefined) { - result.sval = node.sval; + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.funcid !== undefined) { + result.funcid = node.funcid; + } + + if (node.funcresulttype !== undefined) { + result.funcresulttype = node.funcresulttype; + } + + if (node.funcretset !== undefined) { + result.funcretset = node.funcretset; } - if (node.ival !== undefined) { - result.ival = node.ival; + if (node.funcvariadic !== undefined) { + result.funcvariadic = node.funcvariadic; } - if (node.fval !== undefined) { - result.fval = node.fval; + if (node.funcformat !== undefined) { + result.funcformat = node.funcformat; + } + + if (node.funccollid !== undefined) { + result.funccollid = node.funccollid; } - if (node.bsval !== undefined) { - result.bsval = node.bsval; + if (node.inputcollid !== undefined) { + result.inputcollid = node.inputcollid; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); } if (node.location !== undefined) { result.location = node.location; } + return { FuncExpr: result }; + } + + A_Const(node: PG15.A_Const, context: TransformerContext): any { + const result: any = { ...node }; + + if (result.val) { + const val: any = result.val; + if (val.String && val.String.str !== undefined) { + result.sval = val.String.str; + delete result.val; + } else if (val.Integer && val.Integer.ival !== undefined) { + result.ival = val.Integer.ival; + delete result.val; + } else if (val.Float && val.Float.str !== undefined) { + result.fval = val.Float.str; + delete result.val; + } else if (val.BitString && val.BitString.str !== undefined) { + result.bsval = val.BitString.str; + delete result.val; + } else if (val.Null !== undefined) { + delete result.val; + } + } + + if (result.ival !== undefined) { + result.ival = this.transform(result.ival as any, context); + } + return { A_Const: result }; } @@ -620,11 +710,67 @@ export class V15ToV16Transformer { } CaseExpr(node: PG15.CaseExpr, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.casetype !== undefined) { + result.casetype = node.casetype; + } + + if (node.casecollid !== undefined) { + result.casecollid = node.casecollid; + } + + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.defresult !== undefined) { + result.defresult = this.transform(node.defresult as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { CaseExpr: result }; } CoalesceExpr(node: PG15.CoalesceExpr, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.coalescetype !== undefined) { + result.coalescetype = node.coalescetype; + } + + if (node.coalescecollid !== undefined) { + result.coalescecollid = node.coalescecollid; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { CoalesceExpr: result }; } TypeCast(node: PG15.TypeCast, context: TransformerContext): any { @@ -646,69 +792,100 @@ export class V15ToV16Transformer { } CollateClause(node: PG15.CollateClause, context: TransformerContext): any { - return node; - } + const result: any = {}; - BooleanTest(node: PG15.BooleanTest, context: TransformerContext): any { - return node; - } + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } - NullTest(node: PG15.NullTest, context: TransformerContext): any { - return node; + if (node.collname !== undefined) { + result.collname = Array.isArray(node.collname) + ? node.collname.map((item: any) => this.transform(item as any, context)) + : this.transform(node.collname as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { CollateClause: result }; } - String(node: PG15.String, context: TransformerContext): any { + BooleanTest(node: PG15.BooleanTest, context: TransformerContext): any { const result: any = {}; - if (node.sval !== undefined) { - result.sval = node.sval; + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); } - return { String: result }; - } - - Integer(node: PG15.Integer, context: TransformerContext): any { - const result: any = {}; + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } - if (node.ival !== undefined) { - result.ival = node.ival; + if (node.booltesttype !== undefined) { + result.booltesttype = node.booltesttype; } - return { Integer: result }; + if (node.location !== undefined) { + result.location = node.location; + } + + return { BooleanTest: result }; } - - Float(node: PG15.Float, context: TransformerContext): any { + + NullTest(node: PG15.NullTest, context: TransformerContext): any { const result: any = {}; - if (node.fval !== undefined) { - result.fval = node.fval; + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); } - return { Float: result }; - } - - Boolean(node: PG15.Boolean, context: TransformerContext): any { - const result: any = {}; + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } - if (node.boolval !== undefined) { - result.boolval = node.boolval; + if (node.nulltesttype !== undefined) { + result.nulltesttype = node.nulltesttype; } - return { Boolean: result }; - } - - BitString(node: PG15.BitString, context: TransformerContext): any { - const result: any = {}; + if (node.argisrow !== undefined) { + result.argisrow = node.argisrow; + } - if (node.bsval !== undefined) { - result.bsval = node.bsval; + if (node.location !== undefined) { + result.location = node.location; } + return { NullTest: result }; + } + + String(node: PG15.String, context: TransformerContext): any { + const result: any = { ...node }; + return { String: result }; + } + + Integer(node: PG15.Integer, context: TransformerContext): any { + const result: any = { ...node }; + return { Integer: result }; + } + + Float(node: PG15.Float, context: TransformerContext): any { + const result: any = { ...node }; + return { Float: result }; + } + + Boolean(node: PG15.Boolean, context: TransformerContext): any { + const result: any = { ...node }; + return { Boolean: result }; + } + + BitString(node: PG15.BitString, context: TransformerContext): any { + const result: any = { ...node }; return { BitString: result }; } - + Null(node: PG15.Node, context: TransformerContext): any { - return node; + return { Null: {} }; } List(node: PG15.List, context: TransformerContext): any { @@ -747,7 +924,25 @@ export class V15ToV16Transformer { } if (node.partspec !== undefined) { - result.partspec = this.transform(node.partspec as any, context); + // Handle partspec transformation directly since it's a plain object, not a wrapped node + const partspec: any = { ...node.partspec }; + + if (partspec.strategy !== undefined) { + const strategyMap: Record = { + 'range': 'PARTITION_STRATEGY_RANGE', + 'list': 'PARTITION_STRATEGY_LIST', + 'hash': 'PARTITION_STRATEGY_HASH' + }; + partspec.strategy = strategyMap[partspec.strategy] || partspec.strategy; + } + + if (partspec.partParams !== undefined) { + partspec.partParams = Array.isArray(partspec.partParams) + ? partspec.partParams.map((item: any) => this.transform(item as any, context)) + : this.transform(partspec.partParams as any, context); + } + + result.partspec = partspec; } if (node.ofTypename !== undefined) { @@ -793,7 +988,8 @@ export class V15ToV16Transformer { } if (node.typeName !== undefined) { - result.typeName = this.transform(node.typeName as any, context); + const transformedTypeName = this.transform({ TypeName: node.typeName } as any, context); + result.typeName = transformedTypeName.TypeName; } if (node.inhcount !== undefined) { @@ -864,143 +1060,1352 @@ export class V15ToV16Transformer { } Constraint(node: PG15.Constraint, context: TransformerContext): any { - return node; - } + const result: any = {}; - SubLink(node: PG15.SubLink, context: TransformerContext): any { - return node; - } + if (node.contype !== undefined) { + result.contype = node.contype; + } - CaseWhen(node: PG15.CaseWhen, context: TransformerContext): any { - return node; - } + if (node.conname !== undefined) { + result.conname = node.conname; + } - WindowDef(node: PG15.WindowDef, context: TransformerContext): any { - return node; - } + if (node.deferrable !== undefined) { + result.deferrable = node.deferrable; + } - SortBy(node: PG15.SortBy, context: TransformerContext): any { - return node; - } + if (node.initdeferred !== undefined) { + result.initdeferred = node.initdeferred; + } - GroupingSet(node: PG15.GroupingSet, context: TransformerContext): any { - return node; - } + if (node.location !== undefined) { + result.location = node.location; + } - CommonTableExpr(node: PG15.CommonTableExpr, context: TransformerContext): any { - return node; - } + if (node.is_no_inherit !== undefined) { + result.is_no_inherit = node.is_no_inherit; + } - ParamRef(node: PG15.ParamRef, context: TransformerContext): any { - return node; - } + if (node.raw_expr !== undefined) { + result.raw_expr = this.transform(node.raw_expr as any, context); + } - LockingClause(node: any, context: TransformerContext): any { - return node; - } + if (node.cooked_expr !== undefined) { + result.cooked_expr = node.cooked_expr; + } - MinMaxExpr(node: PG15.MinMaxExpr, context: TransformerContext): any { - return node; - } + if (node.generated_when !== undefined) { + result.generated_when = node.generated_when; + } - RowExpr(node: PG15.RowExpr, context: TransformerContext): any { - return node; - } + if (node.keys !== undefined) { + result.keys = Array.isArray(node.keys) + ? node.keys.map((item: any) => this.transform(item as any, context)) + : this.transform(node.keys as any, context); + } - OpExpr(node: PG15.OpExpr, context: TransformerContext): any { - return node; - } + if (node.including !== undefined) { + result.including = Array.isArray(node.including) + ? node.including.map((item: any) => this.transform(item as any, context)) + : this.transform(node.including as any, context); + } - DistinctExpr(node: PG15.DistinctExpr, context: TransformerContext): any { - return node; - } + if (node.exclusions !== undefined) { + result.exclusions = Array.isArray(node.exclusions) + ? node.exclusions.map((item: any) => this.transform(item as any, context)) + : this.transform(node.exclusions as any, context); + } - NullIfExpr(node: PG15.NullIfExpr, context: TransformerContext): any { - return node; - } + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } - ScalarArrayOpExpr(node: PG15.ScalarArrayOpExpr, context: TransformerContext): any { - return node; - } + if (node.indexname !== undefined) { + result.indexname = node.indexname; + } - Aggref(node: PG15.Aggref, context: TransformerContext): any { - return node; - } + if (node.indexspace !== undefined) { + result.indexspace = node.indexspace; + } - WindowFunc(node: PG15.WindowFunc, context: TransformerContext): any { - return node; - } + if (node.reset_default_tblspc !== undefined) { + result.reset_default_tblspc = node.reset_default_tblspc; + } - FieldSelect(node: PG15.FieldSelect, context: TransformerContext): any { - return node; - } + if (node.access_method !== undefined) { + result.access_method = node.access_method; + } + + if (node.where_clause !== undefined) { + result.where_clause = this.transform(node.where_clause as any, context); + } + + if (node.pktable !== undefined) { + result.pktable = this.transform(node.pktable as any, context); + } + + if (node.fk_attrs !== undefined) { + result.fk_attrs = Array.isArray(node.fk_attrs) + ? node.fk_attrs.map((item: any) => this.transform(item as any, context)) + : this.transform(node.fk_attrs as any, context); + } + + if (node.pk_attrs !== undefined) { + result.pk_attrs = Array.isArray(node.pk_attrs) + ? node.pk_attrs.map((item: any) => this.transform(item as any, context)) + : this.transform(node.pk_attrs as any, context); + } + + if (node.fk_matchtype !== undefined) { + result.fk_matchtype = node.fk_matchtype; + } + + if (node.fk_upd_action !== undefined) { + result.fk_upd_action = node.fk_upd_action; + } + + if (node.fk_del_action !== undefined) { + result.fk_del_action = node.fk_del_action; + } + + if (node.old_conpfeqop !== undefined) { + result.old_conpfeqop = Array.isArray(node.old_conpfeqop) + ? node.old_conpfeqop.map((item: any) => this.transform(item as any, context)) + : this.transform(node.old_conpfeqop as any, context); + } + + if (node.old_pktable_oid !== undefined) { + result.old_pktable_oid = node.old_pktable_oid; + } + + if (node.skip_validation !== undefined) { + result.skip_validation = node.skip_validation; + } + + if (node.initially_valid !== undefined) { + result.initially_valid = node.initially_valid; + } + + return { Constraint: result }; + } + + SubLink(node: PG15.SubLink, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.subLinkType !== undefined) { + result.subLinkType = node.subLinkType; + } + + if (node.subLinkId !== undefined) { + result.subLinkId = node.subLinkId; + } + + if (node.testexpr !== undefined) { + result.testexpr = this.transform(node.testexpr as any, context); + } + + if (node.operName !== undefined) { + result.operName = Array.isArray(node.operName) + ? node.operName.map((item: any) => this.transform(item as any, context)) + : this.transform(node.operName as any, context); + } + + if (node.subselect !== undefined) { + result.subselect = this.transform(node.subselect as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { SubLink: result }; + } + + CaseWhen(node: PG15.CaseWhen, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.expr !== undefined) { + result.expr = this.transform(node.expr as any, context); + } + + if (node.result !== undefined) { + result.result = this.transform(node.result as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { CaseWhen: result }; + } + + WindowDef(node: PG15.WindowDef, context: TransformerContext): any { + const result: any = {}; + + if (node.name !== undefined) { + result.name = node.name; + } + + if (node.refname !== undefined) { + result.refname = node.refname; + } + + if (node.partitionClause !== undefined) { + result.partitionClause = Array.isArray(node.partitionClause) + ? node.partitionClause.map((item: any) => this.transform(item as any, context)) + : this.transform(node.partitionClause as any, context); + } + + if (node.orderClause !== undefined) { + result.orderClause = Array.isArray(node.orderClause) + ? node.orderClause.map((item: any) => this.transform(item as any, context)) + : this.transform(node.orderClause as any, context); + } + + if (node.frameOptions !== undefined) { + result.frameOptions = node.frameOptions; + } + + if (node.startOffset !== undefined) { + result.startOffset = this.transform(node.startOffset as any, context); + } + + if (node.endOffset !== undefined) { + result.endOffset = this.transform(node.endOffset as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { WindowDef: result }; + } + + SortBy(node: PG15.SortBy, context: TransformerContext): any { + const result: any = {}; + + if (node.node !== undefined) { + result.node = this.transform(node.node as any, context); + } + + if (node.sortby_dir !== undefined) { + result.sortby_dir = node.sortby_dir; + } + + if (node.sortby_nulls !== undefined) { + result.sortby_nulls = node.sortby_nulls; + } + + if (node.useOp !== undefined) { + result.useOp = Array.isArray(node.useOp) + ? node.useOp.map((item: any) => this.transform(item as any, context)) + : this.transform(node.useOp as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { SortBy: result }; + } + + GroupingSet(node: PG15.GroupingSet, context: TransformerContext): any { + const result: any = {}; + + if (node.kind !== undefined) { + result.kind = node.kind; + } + + if (node.content !== undefined) { + result.content = Array.isArray(node.content) + ? node.content.map((item: any) => this.transform(item as any, context)) + : this.transform(node.content as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { GroupingSet: result }; + } + + CommonTableExpr(node: PG15.CommonTableExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.ctename !== undefined) { + result.ctename = node.ctename; + } + + if (node.aliascolnames !== undefined) { + result.aliascolnames = Array.isArray(node.aliascolnames) + ? node.aliascolnames.map((item: any) => this.transform(item as any, context)) + : this.transform(node.aliascolnames as any, context); + } + + if (node.ctematerialized !== undefined) { + result.ctematerialized = node.ctematerialized; + } + + if (node.ctequery !== undefined) { + result.ctequery = this.transform(node.ctequery as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + if (node.cterecursive !== undefined) { + result.cterecursive = node.cterecursive; + } + + if (node.cterefcount !== undefined) { + result.cterefcount = node.cterefcount; + } + + if (node.ctecolnames !== undefined) { + result.ctecolnames = Array.isArray(node.ctecolnames) + ? node.ctecolnames.map((item: any) => this.transform(item as any, context)) + : this.transform(node.ctecolnames as any, context); + } + + if (node.ctecoltypes !== undefined) { + result.ctecoltypes = Array.isArray(node.ctecoltypes) + ? node.ctecoltypes.map((item: any) => this.transform(item as any, context)) + : this.transform(node.ctecoltypes as any, context); + } + + if (node.ctecoltypmods !== undefined) { + result.ctecoltypmods = Array.isArray(node.ctecoltypmods) + ? node.ctecoltypmods.map((item: any) => this.transform(item as any, context)) + : this.transform(node.ctecoltypmods as any, context); + } + + if (node.ctecolcollations !== undefined) { + result.ctecolcollations = Array.isArray(node.ctecolcollations) + ? node.ctecolcollations.map((item: any) => this.transform(item as any, context)) + : this.transform(node.ctecolcollations as any, context); + } + + return { CommonTableExpr: result }; + } + + ParamRef(node: PG15.ParamRef, context: TransformerContext): any { + const result: any = {}; + + if (node.number !== undefined) { + result.number = node.number; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { ParamRef: result }; + } + + LockingClause(node: any, context: TransformerContext): any { + const result: any = {}; + + if (node.lockedRels !== undefined) { + result.lockedRels = Array.isArray(node.lockedRels) + ? node.lockedRels.map((item: any) => this.transform(item as any, context)) + : this.transform(node.lockedRels as any, context); + } + + if (node.strength !== undefined) { + result.strength = node.strength; + } + + if (node.waitPolicy !== undefined) { + result.waitPolicy = node.waitPolicy; + } + + return { LockingClause: result }; + } + + MinMaxExpr(node: PG15.MinMaxExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.minmaxtype !== undefined) { + result.minmaxtype = node.minmaxtype; + } + + if (node.minmaxcollid !== undefined) { + result.minmaxcollid = node.minmaxcollid; + } + + if (node.inputcollid !== undefined) { + result.inputcollid = node.inputcollid; + } + + if (node.op !== undefined) { + result.op = node.op; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { MinMaxExpr: result }; + } + + RowExpr(node: PG15.RowExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.row_typeid !== undefined) { + result.row_typeid = node.row_typeid; + } + + if (node.row_format !== undefined) { + result.row_format = node.row_format; + } + + if (node.colnames !== undefined) { + result.colnames = Array.isArray(node.colnames) + ? node.colnames.map((item: any) => this.transform(item as any, context)) + : this.transform(node.colnames as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { RowExpr: result }; + } + + OpExpr(node: PG15.OpExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.opno !== undefined) { + result.opno = node.opno; + } + + if (node.opfuncid !== undefined) { + result.opfuncid = node.opfuncid; + } + + if (node.opresulttype !== undefined) { + result.opresulttype = node.opresulttype; + } + + if (node.opretset !== undefined) { + result.opretset = node.opretset; + } + + if (node.opcollid !== undefined) { + result.opcollid = node.opcollid; + } + + if (node.inputcollid !== undefined) { + result.inputcollid = node.inputcollid; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { OpExpr: result }; + } + + DistinctExpr(node: PG15.DistinctExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.opno !== undefined) { + result.opno = node.opno; + } + + if (node.opfuncid !== undefined) { + result.opfuncid = node.opfuncid; + } + + if (node.opresulttype !== undefined) { + result.opresulttype = node.opresulttype; + } + + if (node.opretset !== undefined) { + result.opretset = node.opretset; + } + + if (node.opcollid !== undefined) { + result.opcollid = node.opcollid; + } + + if (node.inputcollid !== undefined) { + result.inputcollid = node.inputcollid; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { DistinctExpr: result }; + } + + NullIfExpr(node: PG15.NullIfExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.opno !== undefined) { + result.opno = node.opno; + } + + if (node.opfuncid !== undefined) { + result.opfuncid = node.opfuncid; + } + + if (node.opresulttype !== undefined) { + result.opresulttype = node.opresulttype; + } + + if (node.opretset !== undefined) { + result.opretset = node.opretset; + } + + if (node.opcollid !== undefined) { + result.opcollid = node.opcollid; + } + + if (node.inputcollid !== undefined) { + result.inputcollid = node.inputcollid; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { NullIfExpr: result }; + } + + ScalarArrayOpExpr(node: PG15.ScalarArrayOpExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.opno !== undefined) { + result.opno = node.opno; + } + + if (node.opfuncid !== undefined) { + result.opfuncid = node.opfuncid; + } + + if (node.hashfuncid !== undefined) { + result.hashfuncid = node.hashfuncid; + } + + if (node.useOr !== undefined) { + result.useOr = node.useOr; + } + + if (node.inputcollid !== undefined) { + result.inputcollid = node.inputcollid; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { ScalarArrayOpExpr: result }; + } + + Aggref(node: PG15.Aggref, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.aggfnoid !== undefined) { + result.aggfnoid = node.aggfnoid; + } + + if (node.aggtype !== undefined) { + result.aggtype = node.aggtype; + } + + if (node.aggcollid !== undefined) { + result.aggcollid = node.aggcollid; + } + + if (node.inputcollid !== undefined) { + result.inputcollid = node.inputcollid; + } + + if (node.aggtranstype !== undefined) { + result.aggtranstype = node.aggtranstype; + } + + if (node.aggargtypes !== undefined) { + result.aggargtypes = Array.isArray(node.aggargtypes) + ? node.aggargtypes.map((item: any) => this.transform(item as any, context)) + : this.transform(node.aggargtypes as any, context); + } + + if (node.aggdirectargs !== undefined) { + result.aggdirectargs = Array.isArray(node.aggdirectargs) + ? node.aggdirectargs.map((item: any) => this.transform(item as any, context)) + : this.transform(node.aggdirectargs as any, context); + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.aggorder !== undefined) { + result.aggorder = Array.isArray(node.aggorder) + ? node.aggorder.map((item: any) => this.transform(item as any, context)) + : this.transform(node.aggorder as any, context); + } + + if (node.aggdistinct !== undefined) { + result.aggdistinct = Array.isArray(node.aggdistinct) + ? node.aggdistinct.map((item: any) => this.transform(item as any, context)) + : this.transform(node.aggdistinct as any, context); + } + + if (node.aggfilter !== undefined) { + result.aggfilter = this.transform(node.aggfilter as any, context); + } + + if (node.aggstar !== undefined) { + result.aggstar = node.aggstar; + } + + if (node.aggvariadic !== undefined) { + result.aggvariadic = node.aggvariadic; + } + + if (node.aggkind !== undefined) { + result.aggkind = node.aggkind; + } + + if (node.agglevelsup !== undefined) { + result.agglevelsup = node.agglevelsup; + } + + if (node.aggsplit !== undefined) { + result.aggsplit = node.aggsplit; + } + + if (node.aggno !== undefined) { + result.aggno = node.aggno; + } + + if (node.aggtransno !== undefined) { + result.aggtransno = node.aggtransno; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { Aggref: result }; + } + + WindowFunc(node: PG15.WindowFunc, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.winfnoid !== undefined) { + result.winfnoid = node.winfnoid; + } + + if (node.wintype !== undefined) { + result.wintype = node.wintype; + } + + if (node.wincollid !== undefined) { + result.wincollid = node.wincollid; + } + + if (node.inputcollid !== undefined) { + result.inputcollid = node.inputcollid; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.aggfilter !== undefined) { + result.aggfilter = this.transform(node.aggfilter as any, context); + } + + if (node.winref !== undefined) { + result.winref = node.winref; + } + + if (node.winstar !== undefined) { + result.winstar = node.winstar; + } + + if (node.winagg !== undefined) { + result.winagg = node.winagg; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { WindowFunc: result }; + } + + FieldSelect(node: PG15.FieldSelect, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } + + if (node.fieldnum !== undefined) { + result.fieldnum = node.fieldnum; + } + + if (node.resulttype !== undefined) { + result.resulttype = node.resulttype; + } + + if (node.resulttypmod !== undefined) { + result.resulttypmod = node.resulttypmod; + } + + if (node.resultcollid !== undefined) { + result.resultcollid = node.resultcollid; + } + + return { FieldSelect: result }; + } + + RelabelType(node: PG15.RelabelType, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } + + if (node.resulttype !== undefined) { + result.resulttype = node.resulttype; + } + + if (node.resulttypmod !== undefined) { + result.resulttypmod = node.resulttypmod; + } + + if (node.resultcollid !== undefined) { + result.resultcollid = node.resultcollid; + } + + if (node.relabelformat !== undefined) { + result.relabelformat = node.relabelformat; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { RelabelType: result }; + } + + CoerceViaIO(node: PG15.CoerceViaIO, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } + + if (node.resulttype !== undefined) { + result.resulttype = node.resulttype; + } + + if (node.resultcollid !== undefined) { + result.resultcollid = node.resultcollid; + } + + if (node.coerceformat !== undefined) { + result.coerceformat = node.coerceformat; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { CoerceViaIO: result }; + } + + ArrayCoerceExpr(node: PG15.ArrayCoerceExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } + + if (node.elemexpr !== undefined) { + result.elemexpr = this.transform(node.elemexpr as any, context); + } + + if (node.resulttype !== undefined) { + result.resulttype = node.resulttype; + } + + if (node.resulttypmod !== undefined) { + result.resulttypmod = node.resulttypmod; + } + + if (node.resultcollid !== undefined) { + result.resultcollid = node.resultcollid; + } + + if (node.coerceformat !== undefined) { + result.coerceformat = node.coerceformat; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { ArrayCoerceExpr: result }; + } + + ConvertRowtypeExpr(node: PG15.ConvertRowtypeExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } + + if (node.resulttype !== undefined) { + result.resulttype = node.resulttype; + } + + if (node.convertformat !== undefined) { + result.convertformat = node.convertformat; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { ConvertRowtypeExpr: result }; + } + + NamedArgExpr(node: PG15.NamedArgExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } + + if (node.name !== undefined) { + result.name = node.name; + } + + if (node.argnumber !== undefined) { + result.argnumber = node.argnumber; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { NamedArgExpr: result }; + } + + ViewStmt(node: PG15.ViewStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.view !== undefined) { + result.view = this.transform(node.view as any, context); + } + + if (node.aliases !== undefined) { + result.aliases = Array.isArray(node.aliases) + ? node.aliases.map((item: any) => this.transform(item as any, context)) + : this.transform(node.aliases as any, context); + } + + if (node.query !== undefined) { + result.query = this.transform(node.query as any, context); + } + + if (node.replace !== undefined) { + result.replace = node.replace; + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + if (node.withCheckOption !== undefined) { + result.withCheckOption = node.withCheckOption; + } + + return { ViewStmt: result }; + } + + IndexStmt(node: PG15.IndexStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.idxname !== undefined) { + result.idxname = node.idxname; + } + + if (node.relation !== undefined) { + result.relation = this.transform(node.relation as any, context); + } + + if (node.accessMethod !== undefined) { + result.accessMethod = node.accessMethod; + } + + if (node.tableSpace !== undefined) { + result.tableSpace = node.tableSpace; + } + + if (node.indexParams !== undefined) { + result.indexParams = Array.isArray(node.indexParams) + ? node.indexParams.map((item: any) => this.transform(item as any, context)) + : this.transform(node.indexParams as any, context); + } + + if (node.indexIncludingParams !== undefined) { + result.indexIncludingParams = Array.isArray(node.indexIncludingParams) + ? node.indexIncludingParams.map((item: any) => this.transform(item as any, context)) + : this.transform(node.indexIncludingParams as any, context); + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + if (node.whereClause !== undefined) { + result.whereClause = this.transform(node.whereClause as any, context); + } + + if (node.excludeOpNames !== undefined) { + result.excludeOpNames = Array.isArray(node.excludeOpNames) + ? node.excludeOpNames.map((item: any) => this.transform(item as any, context)) + : this.transform(node.excludeOpNames as any, context); + } + + if (node.idxcomment !== undefined) { + result.idxcomment = node.idxcomment; + } + + if (node.indexOid !== undefined) { + result.indexOid = node.indexOid; + } + + if (node.oldNode !== undefined) { + result.oldNode = node.oldNode; + } + + if (node.oldCreateSubid !== undefined) { + result.oldCreateSubid = node.oldCreateSubid; + } + + if (node.oldFirstRelfilenodeSubid !== undefined) { + result.oldFirstRelfilenodeSubid = node.oldFirstRelfilenodeSubid; + } + + if (node.unique !== undefined) { + result.unique = node.unique; + } + + if (node.nulls_not_distinct !== undefined) { + result.nulls_not_distinct = node.nulls_not_distinct; + } - RelabelType(node: PG15.RelabelType, context: TransformerContext): any { - return node; - } + if (node.primary !== undefined) { + result.primary = node.primary; + } - CoerceViaIO(node: PG15.CoerceViaIO, context: TransformerContext): any { - return node; - } + if (node.isconstraint !== undefined) { + result.isconstraint = node.isconstraint; + } - ArrayCoerceExpr(node: PG15.ArrayCoerceExpr, context: TransformerContext): any { - return node; - } + if (node.deferrable !== undefined) { + result.deferrable = node.deferrable; + } - ConvertRowtypeExpr(node: PG15.ConvertRowtypeExpr, context: TransformerContext): any { - return node; - } + if (node.initdeferred !== undefined) { + result.initdeferred = node.initdeferred; + } - NamedArgExpr(node: PG15.NamedArgExpr, context: TransformerContext): any { - return node; - } + if (node.transformed !== undefined) { + result.transformed = node.transformed; + } - ViewStmt(node: PG15.ViewStmt, context: TransformerContext): any { - return node; - } + if (node.concurrent !== undefined) { + result.concurrent = node.concurrent; + } - IndexStmt(node: PG15.IndexStmt, context: TransformerContext): any { - return node; + if (node.if_not_exists !== undefined) { + result.if_not_exists = node.if_not_exists; + } + + if (node.reset_default_tblspc !== undefined) { + result.reset_default_tblspc = node.reset_default_tblspc; + } + + return { IndexStmt: result }; } IndexElem(node: PG15.IndexElem, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.name !== undefined) { + result.name = node.name; + } + + if (node.expr !== undefined) { + result.expr = this.transform(node.expr as any, context); + } + + if (node.indexcolname !== undefined) { + result.indexcolname = node.indexcolname; + } + + if (node.collation !== undefined) { + result.collation = Array.isArray(node.collation) + ? node.collation.map((item: any) => this.transform(item as any, context)) + : this.transform(node.collation as any, context); + } + + if (node.opclass !== undefined) { + result.opclass = Array.isArray(node.opclass) + ? node.opclass.map((item: any) => this.transform(item as any, context)) + : this.transform(node.opclass as any, context); + } + + if (node.opclassopts !== undefined) { + result.opclassopts = Array.isArray(node.opclassopts) + ? node.opclassopts.map((item: any) => this.transform(item as any, context)) + : this.transform(node.opclassopts as any, context); + } + + if (node.ordering !== undefined) { + result.ordering = node.ordering; + } + + if (node.nulls_ordering !== undefined) { + result.nulls_ordering = node.nulls_ordering; + } + + return { IndexElem: result }; } PartitionElem(node: PG15.PartitionElem, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.name !== undefined) { + result.name = node.name; + } + + if (node.expr !== undefined) { + result.expr = this.transform(node.expr as any, context); + } + + if (node.collation !== undefined) { + result.collation = Array.isArray(node.collation) + ? node.collation.map((item: any) => this.transform(item as any, context)) + : this.transform(node.collation as any, context); + } + + if (node.opclass !== undefined) { + result.opclass = Array.isArray(node.opclass) + ? node.opclass.map((item: any) => this.transform(item as any, context)) + : this.transform(node.opclass as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { PartitionElem: result }; } PartitionCmd(node: PG15.PartitionCmd, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.name !== undefined) { + result.name = this.transform(node.name as any, context); + } + + if (node.bound !== undefined) { + result.bound = this.transform(node.bound as any, context); + } + + if (node.concurrent !== undefined) { + result.concurrent = node.concurrent; + } + + return { PartitionCmd: result }; } + JoinExpr(node: PG15.JoinExpr, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.jointype !== undefined) { + result.jointype = node.jointype; + } + + if (node.isNatural !== undefined) { + result.isNatural = node.isNatural; + } + + if (node.larg !== undefined) { + result.larg = this.transform(node.larg as any, context); + } + + if (node.rarg !== undefined) { + result.rarg = this.transform(node.rarg as any, context); + } + + if (node.usingClause !== undefined) { + result.usingClause = Array.isArray(node.usingClause) + ? node.usingClause.map((item: any) => this.transform(item as any, context)) + : this.transform(node.usingClause as any, context); + } + + if (node.join_using_alias !== undefined) { + result.join_using_alias = this.transform(node.join_using_alias as any, context); + } + + if (node.quals !== undefined) { + result.quals = this.transform(node.quals as any, context); + } + + if (node.alias !== undefined) { + result.alias = this.transform(node.alias as any, context); + } + + if (node.rtindex !== undefined) { + result.rtindex = node.rtindex; + } + + return { JoinExpr: result }; } FromExpr(node: PG15.FromExpr, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.fromlist !== undefined) { + result.fromlist = Array.isArray(node.fromlist) + ? node.fromlist.map((item: any) => this.transform(item as any, context)) + : this.transform(node.fromlist as any, context); + } + + if (node.quals !== undefined) { + result.quals = this.transform(node.quals as any, context); + } + + return { FromExpr: result }; } TransactionStmt(node: PG15.TransactionStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.kind !== undefined) { + result.kind = node.kind; + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + if (node.savepoint_name !== undefined) { + result.savepoint_name = node.savepoint_name; + } + + if (node.gid !== undefined) { + result.gid = node.gid; + } + + if (node.chain !== undefined) { + result.chain = node.chain; + } + + return { TransactionStmt: result }; } VariableSetStmt(node: PG15.VariableSetStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.kind !== undefined) { + result.kind = node.kind; + } + + if (node.name !== undefined) { + result.name = node.name; + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.is_local !== undefined) { + result.is_local = node.is_local; + } + + return { VariableSetStmt: result }; } VariableShowStmt(node: PG15.VariableShowStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.name !== undefined) { + result.name = node.name; + } + + return { VariableShowStmt: result }; } CreateSchemaStmt(node: PG15.CreateSchemaStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.schemaname !== undefined) { + result.schemaname = node.schemaname; + } + + if (node.authrole !== undefined) { + result.authrole = this.transform(node.authrole as any, context); + } + + if (node.schemaElts !== undefined) { + result.schemaElts = Array.isArray(node.schemaElts) + ? node.schemaElts.map((item: any) => this.transform(item as any, context)) + : this.transform(node.schemaElts as any, context); + } + + if (node.if_not_exists !== undefined) { + result.if_not_exists = node.if_not_exists; + } + + return { CreateSchemaStmt: result }; } RoleSpec(node: PG15.RoleSpec, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.roletype !== undefined) { + result.roletype = node.roletype; + } + + if (node.rolename !== undefined) { + result.rolename = node.rolename; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { RoleSpec: result }; } DropStmt(node: PG15.DropStmt, context: TransformerContext): any { @@ -1032,19 +2437,103 @@ export class V15ToV16Transformer { } TruncateStmt(node: PG15.TruncateStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.relations !== undefined) { + result.relations = Array.isArray(node.relations) + ? node.relations.map((item: any) => this.transform(item as any, context)) + : this.transform(node.relations as any, context); + } + + if (node.restart_seqs !== undefined) { + result.restart_seqs = node.restart_seqs; + } + + if (node.behavior !== undefined) { + result.behavior = node.behavior; + } + + return { TruncateStmt: result }; + } + + ReturnStmt(node: PG15.ReturnStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.returnval !== undefined) { + result.returnval = this.transform(node.returnval as any, context); + } + + return { ReturnStmt: result }; + } + + PLAssignStmt(node: PG15.PLAssignStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.name !== undefined) { + result.name = node.name; + } + + if (node.indirection !== undefined) { + result.indirection = Array.isArray(node.indirection) + ? node.indirection.map((item: any) => this.transform(item as any, context)) + : this.transform(node.indirection as any, context); + } + + if (node.nnames !== undefined) { + result.nnames = node.nnames; + } + + if (node.val !== undefined) { + result.val = this.transform(node.val as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { PLAssignStmt: result }; } - ReturnStmt(node: PG15.ReturnStmt, context: TransformerContext): any { - return node; - } + CopyStmt(node: PG15.CopyStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.relation !== undefined) { + result.relation = this.transform(node.relation as any, context); + } + + if (node.query !== undefined) { + result.query = this.transform(node.query as any, context); + } + + if (node.attlist !== undefined) { + result.attlist = Array.isArray(node.attlist) + ? node.attlist.map((item: any) => this.transform(item as any, context)) + : this.transform(node.attlist as any, context); + } + + if (node.is_from !== undefined) { + result.is_from = node.is_from; + } + + if (node.is_program !== undefined) { + result.is_program = node.is_program; + } + + if (node.filename !== undefined) { + result.filename = node.filename; + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } - PLAssignStmt(node: PG15.PLAssignStmt, context: TransformerContext): any { - return node; - } + if (node.whereClause !== undefined) { + result.whereClause = this.transform(node.whereClause as any, context); + } - CopyStmt(node: PG15.CopyStmt, context: TransformerContext): any { - return node; + return { CopyStmt: result }; } AlterTableStmt(node: PG15.AlterTableStmt, context: TransformerContext): any { @@ -1060,6 +2549,10 @@ export class V15ToV16Transformer { : this.transform(node.cmds as any, context); } + if (node.objtype !== undefined) { + result.objtype = node.objtype; + } + if (node.missing_ok !== undefined) { result.missing_ok = node.missing_ok; } @@ -1102,103 +2595,405 @@ export class V15ToV16Transformer { } CreateFunctionStmt(node: PG15.CreateFunctionStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.is_procedure !== undefined) { + result.is_procedure = node.is_procedure; + } + + if (node.replace !== undefined) { + result.replace = node.replace; + } + + if (node.funcname !== undefined) { + result.funcname = Array.isArray(node.funcname) + ? node.funcname.map((item: any) => this.transform(item as any, context)) + : this.transform(node.funcname as any, context); + } + + if (node.parameters !== undefined) { + result.parameters = Array.isArray(node.parameters) + ? node.parameters.map((item: any) => this.transform(item as any, context)) + : this.transform(node.parameters as any, context); + } + + if (node.returnType !== undefined) { + result.returnType = this.transform(node.returnType as any, context); + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + if (node.sql_body !== undefined) { + result.sql_body = this.transform(node.sql_body as any, context); + } + + return { CreateFunctionStmt: result }; } FunctionParameter(node: PG15.FunctionParameter, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.name !== undefined) { + result.name = node.name; + } + + if (node.argType !== undefined) { + result.argType = this.transform(node.argType as any, context); + } + + if (node.mode !== undefined) { + result.mode = node.mode; + } + + if (node.defexpr !== undefined) { + result.defexpr = this.transform(node.defexpr as any, context); + } + + return { FunctionParameter: result }; + } + + CompositeTypeStmt(node: PG15.CompositeTypeStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.typevar !== undefined) { + result.typevar = this.transform(node.typevar as any, context); + } + + if (node.coldeflist !== undefined) { + result.coldeflist = Array.isArray(node.coldeflist) + ? node.coldeflist.map((item: any) => this.transform(item as any, context)) + : this.transform(node.coldeflist as any, context); + } + + return { CompositeTypeStmt: result }; + } + + DoStmt(node: PG15.DoStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + return { DoStmt: result }; + } + + DefineStmt(node: PG15.DefineStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.kind !== undefined) { + result.kind = node.kind; + } + + if (node.oldstyle !== undefined) { + result.oldstyle = node.oldstyle; + } + + if (node.defnames !== undefined) { + result.defnames = Array.isArray(node.defnames) + ? node.defnames.map((item: any) => this.transform(item as any, context)) + : this.transform(node.defnames as any, context); + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.definition !== undefined) { + result.definition = Array.isArray(node.definition) + ? node.definition.map((item: any) => this.transform(item as any, context)) + : this.transform(node.definition as any, context); + } + + if (node.if_not_exists !== undefined) { + result.if_not_exists = node.if_not_exists; + } + + if (node.replace !== undefined) { + result.replace = node.replace; + } + + return { DefineStmt: result }; + } + + RangeSubselect(node: PG15.RangeSubselect, context: TransformerContext): any { + const result: any = {}; + + if (node.lateral !== undefined) { + result.lateral = node.lateral; + } + + if (node.subquery !== undefined) { + result.subquery = this.transform(node.subquery as any, context); + } + + if (node.alias !== undefined) { + result.alias = this.transform(node.alias as any, context); + } + + return { RangeSubselect: result }; } CreateEnumStmt(node: PG15.CreateEnumStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.typeName !== undefined) { + result.typeName = Array.isArray(node.typeName) + ? node.typeName.map((item: any) => this.transform(item as any, context)) + : this.transform(node.typeName as any, context); + } + + if (node.vals !== undefined) { + result.vals = Array.isArray(node.vals) + ? node.vals.map((item: any) => this.transform(item as any, context)) + : this.transform(node.vals as any, context); + } + + return { CreateEnumStmt: result }; } CreateDomainStmt(node: PG15.CreateDomainStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.domainname !== undefined) { + result.domainname = Array.isArray(node.domainname) + ? node.domainname.map((item: any) => this.transform(item as any, context)) + : this.transform(node.domainname as any, context); + } + + if (node.typeName !== undefined) { + result.typeName = this.transform(node.typeName as any, context); + } + + if (node.collClause !== undefined) { + result.collClause = this.transform(node.collClause as any, context); + } + + if (node.constraints !== undefined) { + result.constraints = Array.isArray(node.constraints) + ? node.constraints.map((item: any) => this.transform(item as any, context)) + : this.transform(node.constraints as any, context); + } + + return { CreateDomainStmt: result }; } CreateRoleStmt(node: PG15.CreateRoleStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.stmt_type !== undefined) { + result.stmt_type = node.stmt_type; + } + + if (node.role !== undefined) { + result.role = node.role; + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + return { CreateRoleStmt: result }; } DefElem(node: PG15.DefElem, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.defnamespace !== undefined) { + result.defnamespace = node.defnamespace; + } + + if (node.defname !== undefined) { + result.defname = node.defname; + } + + if (node.arg !== undefined) { + result.arg = this.transform(node.arg as any, context); + } + + if (node.defaction !== undefined) { + result.defaction = node.defaction; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { DefElem: result }; } CreateTableSpaceStmt(node: PG15.CreateTableSpaceStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.tablespacename !== undefined) { + result.tablespacename = node.tablespacename; + } + + if (node.owner !== undefined) { + result.owner = this.transform(node.owner as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + return { CreateTableSpaceStmt: result }; } DropTableSpaceStmt(node: PG15.DropTableSpaceStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.tablespacename !== undefined) { + result.tablespacename = node.tablespacename; + } + + if (node.missing_ok !== undefined) { + result.missing_ok = node.missing_ok; + } + + return { DropTableSpaceStmt: result }; } AlterTableSpaceOptionsStmt(node: PG15.AlterTableSpaceOptionsStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.tablespacename !== undefined) { + result.tablespacename = node.tablespacename; + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + if (node.isReset !== undefined) { + result.isReset = node.isReset; + } + + return { AlterTableSpaceOptionsStmt: result }; } CreateExtensionStmt(node: PG15.CreateExtensionStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.extname !== undefined) { + result.extname = node.extname; + } + + if (node.if_not_exists !== undefined) { + result.if_not_exists = node.if_not_exists; + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + return { CreateExtensionStmt: result }; } AlterExtensionStmt(node: PG15.AlterExtensionStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.extname !== undefined) { + result.extname = node.extname; + } + + if (node.options !== undefined) { + result.options = Array.isArray(node.options) + ? node.options.map((item: any) => this.transform(item as any, context)) + : this.transform(node.options as any, context); + } + + return { AlterExtensionStmt: result }; } CreateFdwStmt(node: PG15.CreateFdwStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateFdwStmt: result }; } SetOperationStmt(node: PG15.SetOperationStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { SetOperationStmt: result }; } ReplicaIdentityStmt(node: PG15.ReplicaIdentityStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ReplicaIdentityStmt: result }; } AlterCollationStmt(node: PG15.AlterCollationStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterCollationStmt: result }; } AlterDomainStmt(node: PG15.AlterDomainStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterDomainStmt: result }; } PrepareStmt(node: PG15.PrepareStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { PrepareStmt: result }; } ExecuteStmt(node: PG15.ExecuteStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ExecuteStmt: result }; } DeallocateStmt(node: PG15.DeallocateStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { DeallocateStmt: result }; } NotifyStmt(node: PG15.NotifyStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { NotifyStmt: result }; } ListenStmt(node: PG15.ListenStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ListenStmt: result }; } UnlistenStmt(node: PG15.UnlistenStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { UnlistenStmt: result }; } CheckPointStmt(node: PG15.CheckPointStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CheckPointStmt: result }; } LoadStmt(node: PG15.LoadStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { LoadStmt: result }; } DiscardStmt(node: PG15.DiscardStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { DiscardStmt: result }; } CommentStmt(node: PG15.CommentStmt, context: TransformerContext): any { @@ -1220,410 +3015,673 @@ export class V15ToV16Transformer { } LockStmt(node: PG15.LockStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { LockStmt: result }; } CreatePolicyStmt(node: PG15.CreatePolicyStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreatePolicyStmt: result }; } AlterPolicyStmt(node: PG15.AlterPolicyStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterPolicyStmt: result }; } CreateUserMappingStmt(node: PG15.CreateUserMappingStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateUserMappingStmt: result }; } CreateStatsStmt(node: PG15.CreateStatsStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateStatsStmt: result }; } StatsElem(node: PG15.StatsElem, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { StatsElem: result }; } CreatePublicationStmt(node: PG15.CreatePublicationStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreatePublicationStmt: result }; } CreateSubscriptionStmt(node: PG15.CreateSubscriptionStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateSubscriptionStmt: result }; } AlterPublicationStmt(node: PG15.AlterPublicationStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterPublicationStmt: result }; } AlterSubscriptionStmt(node: PG15.AlterSubscriptionStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterSubscriptionStmt: result }; } DropSubscriptionStmt(node: PG15.DropSubscriptionStmt, context: TransformerContext): any { - return node; - } - - DoStmt(node: PG15.DoStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { DropSubscriptionStmt: result }; } InlineCodeBlock(node: PG15.InlineCodeBlock, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { InlineCodeBlock: result }; } CallContext(node: PG15.CallContext, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CallContext: result }; } ConstraintsSetStmt(node: PG15.ConstraintsSetStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ConstraintsSetStmt: result }; } AlterSystemStmt(node: PG15.AlterSystemStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterSystemStmt: result }; } VacuumRelation(node: PG15.VacuumRelation, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { VacuumRelation: result }; } DropOwnedStmt(node: PG15.DropOwnedStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { DropOwnedStmt: result }; } ReassignOwnedStmt(node: PG15.ReassignOwnedStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ReassignOwnedStmt: result }; } AlterTSDictionaryStmt(node: PG15.AlterTSDictionaryStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterTSDictionaryStmt: result }; } AlterTSConfigurationStmt(node: PG15.AlterTSConfigurationStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterTSConfigurationStmt: result }; } ClosePortalStmt(node: PG15.ClosePortalStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ClosePortalStmt: result }; } FetchStmt(node: PG15.FetchStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { FetchStmt: result }; } AlterStatsStmt(node: PG15.AlterStatsStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterStatsStmt: result }; } ObjectWithArgs(node: PG15.ObjectWithArgs, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ObjectWithArgs: result }; } AlterOperatorStmt(node: PG15.AlterOperatorStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterOperatorStmt: result }; } AlterFdwStmt(node: PG15.AlterFdwStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterFdwStmt: result }; } CreateForeignServerStmt(node: PG15.CreateForeignServerStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateForeignServerStmt: result }; } AlterForeignServerStmt(node: PG15.AlterForeignServerStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterForeignServerStmt: result }; } AlterUserMappingStmt(node: PG15.AlterUserMappingStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterUserMappingStmt: result }; } DropUserMappingStmt(node: PG15.DropUserMappingStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { DropUserMappingStmt: result }; } ImportForeignSchemaStmt(node: PG15.ImportForeignSchemaStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ImportForeignSchemaStmt: result }; } ClusterStmt(node: PG15.ClusterStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ClusterStmt: result }; } VacuumStmt(node: PG15.VacuumStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { VacuumStmt: result }; } ExplainStmt(node: PG15.ExplainStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ExplainStmt: result }; } ReindexStmt(node: PG15.ReindexStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ReindexStmt: result }; } CallStmt(node: PG15.CallStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CallStmt: result }; } CreatedbStmt(node: PG15.CreatedbStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreatedbStmt: result }; } DropdbStmt(node: PG15.DropdbStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { DropdbStmt: result }; } RenameStmt(node: PG15.RenameStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { RenameStmt: result }; } AlterOwnerStmt(node: PG15.AlterOwnerStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterOwnerStmt: result }; } - GrantStmt(node: PG15.GrantStmt, context: TransformerContext): any { - return node; - } GrantRoleStmt(node: PG15.GrantRoleStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { GrantRoleStmt: result }; } SecLabelStmt(node: PG15.SecLabelStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { SecLabelStmt: result }; } AlterDefaultPrivilegesStmt(node: PG15.AlterDefaultPrivilegesStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterDefaultPrivilegesStmt: result }; } CreateConversionStmt(node: PG15.CreateConversionStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateConversionStmt: result }; } CreateCastStmt(node: PG15.CreateCastStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateCastStmt: result }; } CreatePLangStmt(node: PG15.CreatePLangStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreatePLangStmt: result }; } CreateTransformStmt(node: PG15.CreateTransformStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateTransformStmt: result }; } CreateTrigStmt(node: PG15.CreateTrigStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateTrigStmt: result }; } TriggerTransition(node: PG15.TriggerTransition, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { TriggerTransition: result }; } CreateEventTrigStmt(node: PG15.CreateEventTrigStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateEventTrigStmt: result }; } AlterEventTrigStmt(node: PG15.AlterEventTrigStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterEventTrigStmt: result }; } CreateOpClassStmt(node: PG15.CreateOpClassStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateOpClassStmt: result }; } CreateOpFamilyStmt(node: PG15.CreateOpFamilyStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateOpFamilyStmt: result }; } AlterOpFamilyStmt(node: PG15.AlterOpFamilyStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterOpFamilyStmt: result }; } MergeStmt(node: PG15.MergeStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { MergeStmt: result }; } AlterTableMoveAllStmt(node: PG15.AlterTableMoveAllStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterTableMoveAllStmt: result }; } CreateSeqStmt(node: PG15.CreateSeqStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateSeqStmt: result }; } AlterSeqStmt(node: PG15.AlterSeqStmt, context: TransformerContext): any { - return node; - } - - CompositeTypeStmt(node: PG15.CompositeTypeStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterSeqStmt: result }; } CreateRangeStmt(node: PG15.CreateRangeStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateRangeStmt: result }; } AlterEnumStmt(node: PG15.AlterEnumStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterEnumStmt: result }; } AlterTypeStmt(node: PG15.AlterTypeStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterTypeStmt: result }; } AlterRoleStmt(node: PG15.AlterRoleStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterRoleStmt: result }; } - DropRoleStmt(node: PG15.DropRoleStmt, context: TransformerContext): any { - return node; - } CreateAggregateStmt(node: PG15.DefineStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateAggregateStmt: result }; } CreateTableAsStmt(node: PG15.CreateTableAsStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateTableAsStmt: result }; } RefreshMatViewStmt(node: PG15.RefreshMatViewStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { RefreshMatViewStmt: result }; } AccessPriv(node: PG15.AccessPriv, context: TransformerContext): any { - return node; - } - - DefineStmt(node: PG15.DefineStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AccessPriv: result }; } AlterDatabaseStmt(node: PG15.AlterDatabaseStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterDatabaseStmt: result }; } AlterDatabaseRefreshCollStmt(node: PG15.AlterDatabaseRefreshCollStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterDatabaseRefreshCollStmt: result }; } AlterDatabaseSetStmt(node: PG15.AlterDatabaseSetStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterDatabaseSetStmt: result }; } DeclareCursorStmt(node: PG15.DeclareCursorStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { DeclareCursorStmt: result }; } PublicationObjSpec(node: PG15.PublicationObjSpec, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { PublicationObjSpec: result }; } PublicationTable(node: PG15.PublicationTable, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { PublicationTable: result }; } CreateAmStmt(node: PG15.CreateAmStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateAmStmt: result }; } IntoClause(node: PG15.IntoClause, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { IntoClause: result }; } OnConflictExpr(node: PG15.OnConflictExpr, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { OnConflictExpr: result }; } ScanToken(node: PG15.ScanToken, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { ScanToken: result }; } CreateOpClassItem(node: PG15.CreateOpClassItem, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CreateOpClassItem: result }; } Var(node: PG15.Var, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { Var: result }; } TableFunc(node: PG15.TableFunc, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { TableFunc: result }; } RangeTableFunc(node: PG15.RangeTableFunc, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { RangeTableFunc: result }; } RangeTableFuncCol(node: PG15.RangeTableFuncCol, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { RangeTableFuncCol: result }; } RangeFunction(node: PG15.RangeFunction, context: TransformerContext): any { - return node; - } + const result: any = {}; - XmlExpr(node: PG15.XmlExpr, context: TransformerContext): any { - return node; + if (node.lateral !== undefined) { + result.lateral = node.lateral; + } + + if (node.ordinality !== undefined) { + result.ordinality = node.ordinality; + } + + if (node.is_rowsfrom !== undefined) { + result.is_rowsfrom = node.is_rowsfrom; + } + + if (node.functions !== undefined) { + result.functions = Array.isArray(node.functions) + ? node.functions.map((item: any) => this.transform(item as any, context)) + : this.transform(node.functions as any, context); + } + + if (node.alias !== undefined) { + result.alias = this.transform(node.alias as any, context); + } + + if (node.coldeflist !== undefined) { + result.coldeflist = Array.isArray(node.coldeflist) + ? node.coldeflist.map((item: any) => this.transform(item as any, context)) + : this.transform(node.coldeflist as any, context); + } + + return { RangeFunction: result }; } + RangeTableSample(node: PG15.RangeTableSample, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.relation !== undefined) { + result.relation = this.transform(node.relation as any, context); + } + + if (node.method !== undefined) { + result.method = Array.isArray(node.method) + ? node.method.map((item: any) => this.transform(item as any, context)) + : this.transform(node.method as any, context); + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.repeatable !== undefined) { + result.repeatable = this.transform(node.repeatable as any, context); + } + + return { RangeTableSample: result }; } XmlSerialize(node: PG15.XmlSerialize, context: TransformerContext): any { - return node; - } + const result: any = {}; - RuleStmt(node: PG15.RuleStmt, context: TransformerContext): any { - return node; + if (node.xmloption !== undefined) { + result.xmloption = node.xmloption; + } + + if (node.expr !== undefined) { + result.expr = this.transform(node.expr as any, context); + } + + if (node.typeName !== undefined) { + result.typeName = this.transform(node.typeName as any, context); + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { XmlSerialize: result }; } - RangeSubselect(node: PG15.RangeSubselect, context: TransformerContext): any { - return node; + RuleStmt(node: PG15.RuleStmt, context: TransformerContext): any { + const result: any = { ...node }; + return { RuleStmt: result }; } SQLValueFunction(node: PG15.SQLValueFunction, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { SQLValueFunction: result }; } GroupingFunc(node: PG15.GroupingFunc, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { GroupingFunc: result }; } MultiAssignRef(node: PG15.MultiAssignRef, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { MultiAssignRef: result }; } SetToDefault(node: PG15.SetToDefault, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { SetToDefault: result }; } CurrentOfExpr(node: PG15.CurrentOfExpr, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { CurrentOfExpr: result }; } TableLikeClause(node: PG15.TableLikeClause, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { TableLikeClause: result }; } AlterFunctionStmt(node: PG15.AlterFunctionStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterFunctionStmt: result }; } AlterObjectSchemaStmt(node: PG15.AlterObjectSchemaStmt, context: TransformerContext): any { - return node; + const result: any = { ...node }; + return { AlterObjectSchemaStmt: result }; + } + + + CreateForeignTableStmt(node: PG15.CreateForeignTableStmt, context: TransformerContext): any { + const result: any = { ...node }; + return { CreateForeignTableStmt: result }; + } + + DropRoleStmt(node: PG15.DropRoleStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.missing_ok !== undefined) { + result.missing_ok = node.missing_ok; + } + + if (node.roles !== undefined) { + result.roles = Array.isArray(node.roles) + ? node.roles.map((item: any) => this.transform(item as any, context)) + : this.transform(node.roles as any, context); + } + + return { DropRoleStmt: result }; + } + + XmlExpr(node: PG15.XmlExpr, context: TransformerContext): any { + const result: any = {}; + + if (node.xpr !== undefined) { + result.xpr = this.transform(node.xpr as any, context); + } + + if (node.op !== undefined) { + result.op = node.op; + } + + if (node.name !== undefined) { + result.name = node.name; + } + + if (node.named_args !== undefined) { + result.named_args = Array.isArray(node.named_args) + ? node.named_args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.named_args as any, context); + } + + if (node.arg_names !== undefined) { + result.arg_names = Array.isArray(node.arg_names) + ? node.arg_names.map((item: any) => this.transform(item as any, context)) + : this.transform(node.arg_names as any, context); + } + + if (node.args !== undefined) { + result.args = Array.isArray(node.args) + ? node.args.map((item: any) => this.transform(item as any, context)) + : this.transform(node.args as any, context); + } + + if (node.xmloption !== undefined) { + result.xmloption = node.xmloption; + } + + if (node.type !== undefined) { + result.type = node.type; + } + + if (node.typmod !== undefined) { + result.typmod = node.typmod; + } + + if (node.location !== undefined) { + result.location = node.location; + } + + return { XmlExpr: result }; } AlterRoleSetStmt(node: PG15.AlterRoleSetStmt, context: TransformerContext): any { - return node; + const result: any = {}; + + if (node.role !== undefined) { + result.role = this.transform(node.role as any, context); + } + + if (node.database !== undefined) { + result.database = node.database; + } + + if (node.setstmt !== undefined) { + result.setstmt = this.transform(node.setstmt as any, context); + } + + return { AlterRoleSetStmt: result }; } - CreateForeignTableStmt(node: PG15.CreateForeignTableStmt, context: TransformerContext): any { - return node; + GrantStmt(node: PG15.GrantStmt, context: TransformerContext): any { + const result: any = {}; + + if (node.is_grant !== undefined) { + result.is_grant = node.is_grant; + } + + if (node.targtype !== undefined) { + result.targtype = node.targtype; + } + + if (node.objtype !== undefined) { + result.objtype = node.objtype; + } + + if (node.objects !== undefined) { + result.objects = Array.isArray(node.objects) + ? node.objects.map((item: any) => this.transform(item as any, context)) + : this.transform(node.objects as any, context); + } + + if (node.privileges !== undefined) { + result.privileges = Array.isArray(node.privileges) + ? node.privileges.map((item: any) => this.transform(item as any, context)) + : this.transform(node.privileges as any, context); + } + + if (node.grantees !== undefined) { + result.grantees = Array.isArray(node.grantees) + ? node.grantees.map((item: any) => this.transform(item as any, context)) + : this.transform(node.grantees as any, context); + } + + if (node.grant_option !== undefined) { + result.grant_option = node.grant_option; + } + + if (node.behavior !== undefined) { + result.behavior = node.behavior; + } + + return { GrantStmt: result }; } }