Skip to content

Conversation

@pyramation
Copy link
Collaborator

@pyramation pyramation commented Nov 23, 2025

Fix walk function to traverse WithClause and union larg/rarg nodes

Summary

Fixes #216 by updating the walk function in the traverse package to properly handle fields with specific node types (like WithClause, SelectStmt) instead of only traversing fields explicitly marked as type 'Node'.

The Problem: The walk function was only traversing fields where field.type === 'Node', but some fields in the runtime schema have specific types like 'WithClause' or 'SelectStmt'. This caused the traversal to skip:

  • withClause fields (type: 'WithClause')
  • larg and rarg fields in union operations (type: 'SelectStmt')

The Solution: Modified the traversal logic to check if a field's type exists in the schemaMap (meaning it's a valid node type), not just if it's explicitly 'Node'. This allows traversal of all 268 node types defined in the schema.

Changes:

  • Updated packages/traverse/src/traverse.ts to check schemaMap.has(field.type) in addition to field.type === 'Node'
  • Added test case for WithClause traversal
  • Added test case for union larg/rarg traversal
  • Minor auto-formatting changes from ESLint (import ordering, indentation)

Review & Testing Checklist for Human

  • Test with real SQL queries: Verify the fix works with actual SQL containing WITH clauses (CTEs) and UNION operations. Parse a query, walk the AST, and confirm all nodes are visited.
  • Verify scope of change: This change affects traversal of ALL node types in the schema (268 types), not just WithClause and SelectStmt. Review if this broader behavior is correct and doesn't cause unintended side effects.
  • Check test coverage: Review the two new test cases to ensure they adequately demonstrate the fix. Consider if additional test cases are needed for other previously-skipped node types.

Test Plan

import { parse } from 'pgsql-parser';
import { walk } from '@pgsql/traverse';

// Test WITH clause
const withQuery = 'WITH cte AS (SELECT 1) SELECT * FROM cte';
const withAst = parse(withQuery);
const withNodes: string[] = [];
walk(withAst, (path) => { withNodes.push(path.tag); });
console.log('WITH clause nodes:', withNodes);
// Should include: SelectStmt, WithClause, CommonTableExpr, SelectStmt (nested)

// Test UNION
const unionQuery = 'SELECT 1 UNION SELECT 2';
const unionAst = parse(unionQuery);
const unionNodes: string[] = [];
walk(unionAst, (path) => { unionNodes.push(path.tag); });
console.log('UNION nodes:', unionNodes);
// Should include: SelectStmt (parent), SelectStmt (larg), SelectStmt (rarg)

Notes

- Modified walk function to check if field type is any node type (not just 'Node')
- Added logic to use schemaMap to determine if a field type is a node
- Added test cases for WithClause traversal
- Added test cases for union larg/rarg traversal
- Fixes #216

Co-Authored-By: Dan Lynch <[email protected]>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@pyramation pyramation closed this Nov 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Walk doesn't traverse with clause

2 participants