feat(plpgsql-deparser): add hydratePlpgsqlAst for parsing embedded SQL expressions#254
Merged
pyramation merged 6 commits intomainfrom Dec 31, 2025
Merged
feat(plpgsql-deparser): add hydratePlpgsqlAst for parsing embedded SQL expressions#254pyramation merged 6 commits intomainfrom
pyramation merged 6 commits intomainfrom
Conversation
…L expressions - Add hydrate-types.ts with discriminated union types for hydrated expressions: - HydratedExprRaw: fallback for unparseable expressions - HydratedExprSqlExpr: for SQL expressions parsed via SELECT wrapper - HydratedExprSqlStmt: for full SQL statements - HydratedExprAssign: for PL/pgSQL assignments with parsed target/value - Add hydrate.ts with hydratePlpgsqlAst() function that: - Walks the PL/pgSQL AST and parses each PLpgSQL_expr.query string - Handles parseMode 2 (expressions) by wrapping with SELECT - Handles parseMode 3 (assignments) by splitting on := using tokenizer - Returns enriched AST with parsed SQL nodes where possible - Tracks hydration stats and errors for debugging - Add utility functions: - isHydratedExpr(): type guard for hydrated expressions - getOriginalQuery(): extract original query string from hydrated or raw - Export new types and functions from package index - Add comprehensive tests for hydration functionality
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
- Add dehydratePlpgsqlAst() function that converts hydrated AST back to string format
- For 'assign' kind, reconstructs string from target/value fields (enables AST-level modifications)
- For other kinds, uses original string
- Add hydrate-demo.test.ts demonstrating full pipeline with big-function.sql:
- Parse: 68 expressions parsed (20 assignments, 48 SQL expressions, 0 failures)
- Hydrate: Convert query strings to structured objects
- Modify: Change assignment targets (v_discount -> v_discount_MODIFIED, v_tax -> v_tax_MODIFIED)
and default values (0 -> 888)
- Dehydrate: Convert back to string format
- Deparse: Output modified PL/pgSQL code
This proves the full parse -> hydrate -> modify -> dehydrate -> deparse pipeline works.
…ydrate-demo - Remove all console.log statements from hydrate-demo test - Add snapshot test for modified big-function.sql output - Verify exact hydration stats (68 total, 20 assignments, 48 SQL expressions)
- Parse full SQL statement to get CREATE FUNCTION wrapper - Modify function name: big_kitchen_sink -> big_kitchen_sink_MODIFIED - Include RETURNS TABLE clause in snapshot - Demonstrate full pipeline: SQL parse -> PL/pgSQL hydrate -> modify -> dehydrate -> SQL deparse
…ames - Enable pretty print option for SQL deparser - Rename function: big_kitchen_sink -> order_rollup_calculator - Rename variables: v_discount -> v_rebate, v_tax -> v_levy - Change default values: 0 -> 42
…TURNS TABLE - Add context.isPretty() check in CreateFunctionStmt handler - Format function parameters on separate lines in pretty mode - Format RETURNS TABLE columns on separate lines in pretty mode - Update plpgsql-deparser to use workspace pgsql-deparser dependency - Update snapshots to reflect new pretty printing format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(plpgsql-deparser): add hydratePlpgsqlAst for parsing embedded SQL expressions
Summary
Adds a new
hydratePlpgsqlAst()function that walks PL/pgSQL ASTs and parses the embedded SQL expression strings (PLpgSQL_expr.query) into full SQL AST nodes. This enables downstream tooling to work with structured SQL ASTs instead of opaque strings.The implementation uses a discriminated union type system with four expression kinds:
raw- fallback for unparseable expressionssql-expr- expressions parsed viaSELECT <expr>wrapper (parseMode 2)sql-stmt- full SQL statements (parseMode 0)assign- PL/pgSQL assignments split into target/value with parsed ASTs (parseMode 3)Key features:
scanSync) to safely split assignments on:=while respecting nestingrawkindisHydratedExpr()type guard andgetOriginalQuery()helperUpdates since last revision
Deparser pretty printing for CREATE FUNCTION - Added
context.isPretty()checks inCreateFunctionStmthandler to format function parameters andRETURNS TABLEcolumns on separate lines in pretty mode. This is a change to the corepgsql-deparserpackage.Workspace dependency -
plpgsql-deparsernow usesworkspace:*forpgsql-deparserdependency to ensure it uses the local workspace version during development.Creative lowercase naming - Demo uses realistic name transformations instead of
_MODIFIEDsuffixes:big_kitchen_sink→order_rollup_calculatorv_discount→v_rebate,v_tax→v_levy0→42Full CREATE FUNCTION support - The demo test parses the full SQL statement and outputs the complete
CREATE OR REPLACE FUNCTIONdeclaration includingRETURNS TABLEclause, parameters, and language specification.dehydratePlpgsqlAst()- Converts hydrated AST back to canonical string format for deparsing. Forassignkind, reconstructs the string fromtargetandvaluefields, enabling AST-level modifications to be reflected in the output.Review & Testing Checklist for Human
CreateFunctionStmtchanges affect ALL functions in pretty mode. Review the updated snapshots inpackages/deparser/__tests__/pretty/__snapshots__/to ensure the new multiline format is acceptable.workspace:*dependency inplpgsql-deparser/package.jsonshould be transformed to a version number during publish. Verify this works correctly with your publish workflow.END IF;placement, inconsistent whitespace). The PL/pgSQL body formatting is not as clean as the SQL wrapper.v_discountandv_taxassignments are renamed. Other references still use original names.Recommended test plan:
npm testinpackages/deparser- verify 7 pre-existing failures, no new failuresnpm testinpackages/plpgsql-deparser- all 23 tests should pass with 9 snapshotsNotes