{"id":14813,"library":"plpgsql-parser","title":"PostgreSQL SQL & PL/pgSQL AST Parser (@pgsql/parser)","description":"The `@pgsql/parser` package is a core component within a comprehensive monorepo for PostgreSQL Abstract Syntax Tree (AST) parsing, manipulation, and code generation. It provides a robust, multi-version PostgreSQL parser capable of converting SQL and PL/pgSQL queries into hydrated ASTs, supporting PostgreSQL versions 13 through 17. The current stable version for `@pgsql/parser` is approximately 17.0.4, with active development and frequent updates across the monorepo's packages, such as `@pgsql/deparser` (around 0.7.3). Key differentiators include its direct integration with `libpg-query` (the actual PostgreSQL parser exposed for Node.js), offering high fidelity to PostgreSQL's native parsing logic. It also ships with extensive TypeScript type definitions (`@pgsql/types`), utilities for programmatic AST construction (`@pgsql/utils`), and traversal tools (`@pgsql/traverse`), making it suitable for advanced static analysis, query transformation, and code generation tasks. This library aims to provide a complete toolkit for working with PostgreSQL at the AST level.","status":"active","version":"0.5.8","language":"javascript","source_language":"en","source_url":"https://github.com/constructive-io/pgsql-parser","tags":["javascript","sql","postgres","postgresql","pg","plpgsql","query","ast","parser","typescript"],"install":[{"cmd":"npm install plpgsql-parser","lang":"bash","label":"npm"},{"cmd":"yarn add plpgsql-parser","lang":"bash","label":"yarn"},{"cmd":"pnpm add plpgsql-parser","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Provides the underlying C-based PostgreSQL parser for Node.js, essential for core parsing functionality.","package":"libpg-query","optional":false}],"imports":[{"note":"The primary parsing function. For CommonJS, use `require('@pgsql/parser').parse`. The `pgsql-parser` entrypoint in the monorepo might not directly expose `parse` in older versions or without specific imports. Prefer scoped package.","wrong":"const { parse } = require('pgsql-parser');","symbol":"parse","correct":"import { parse } from '@pgsql/parser';"},{"note":"Deparsing (converting AST back to SQL) is typically handled by the separate `@pgsql/deparser` package for a lighter-weight dependency when only deparsing is needed.","wrong":"import { deparse } from '@pgsql/parser';","symbol":"deparse","correct":"import { deparse } from '@pgsql/deparser';"},{"note":"TypeScript types for AST nodes are provided by the `@pgsql/types` package, ensuring type safety when working with the AST structure. Use `import type` for type-only imports.","wrong":"import { SelectStmt } from '@pgsql/parser';","symbol":"SelectStmt","correct":"import type { SelectStmt } from '@pgsql/types';"}],"quickstart":{"code":"import { parse } from '@pgsql/parser';\nimport { deparse } from '@pgsql/deparser';\nimport type { SelectStmt } from '@pgsql/types';\n\nasync function processSqlQuery(sql: string) {\n  try {\n    console.log(`Parsing SQL: ${sql}`);\n    // Parse the SQL query into an Abstract Syntax Tree (AST)\n    const ast = await parse(sql);\n    console.log('Parsed AST (partial):', JSON.stringify(ast.stmts[0]?.stmt, null, 2));\n\n    // Example: Accessing a specific type of statement and its properties\n    if (ast.stmts[0]?.stmt.SelectStmt) {\n      const selectStmt = ast.stmts[0].stmt.SelectStmt as SelectStmt;\n      console.log('Target list items:', selectStmt.targetList?.map(t => JSON.stringify(t.ResTarget?.val)));\n    }\n\n    // Convert the AST back to SQL (deparse)\n    const deparsedSql = await deparse(ast);\n    console.log(`Deparsed SQL: ${deparsedSql}`);\n\n  } catch (error: any) {\n    console.error('Error processing SQL:', error.message);\n    if (error.sqlDetails) {\n      console.error('SQL Details:', error.sqlDetails);\n    }\n  }\n}\n\n// Example SQL queries\nprocessSqlQuery('SELECT id, name FROM users WHERE status = $1 ORDER BY created_at DESC;');\nprocessSqlQuery('CREATE FUNCTION add(a INT, b INT) RETURNS INT LANGUAGE plpgsql AS $$ BEGIN RETURN a + b; END; $$;');\n// Intentionally malformed SQL to demonstrate error handling\n// processSqlQuery('SELECT * FROM users WHERE;');","lang":"typescript","description":"Demonstrates parsing a SQL query into an AST, inspecting the AST (specifically a SELECT statement's target list), and then deparsing the AST back into a SQL string. Includes error handling for invalid SQL and shows a PL/pgSQL function parsing."},"warnings":[{"fix":"Migrate to `@pgsql/parser@^17.0.0` and update import paths and API calls according to the latest documentation within the `constructive-io/pgsql-parser` monorepo. Install specific sub-packages, e.g., `npm install @pgsql/parser @pgsql/deparser @pgsql/types`.","message":"The package `plpgsql-parser` with version `0.5.8` as specified is likely an outdated reference. The current, actively maintained parser from the `constructive-io/pgsql-parser` monorepo is `@pgsql/parser`, which is at major version `17.x.x`. Users should install `@pgsql/parser` and other scoped packages like `@pgsql/deparser` and `@pgsql/types`.","severity":"breaking","affected_versions":"<17.0.0"},{"fix":"Always explicitly import from the scoped packages, e.g., `import { parse } from '@pgsql/parser';`.","message":"The package structure is a monorepo. While a top-level `pgsql-parser` package might exist in the monorepo, the recommended and actively developed components for parsing, deparsing, and types are the scoped packages (`@pgsql/parser`, `@pgsql/deparser`, `@pgsql/types`, etc.). Relying on a non-scoped `pgsql-parser` may lead to outdated versions or missing functionalities.","severity":"gotcha","affected_versions":"All"},{"fix":"Always consult the changelog of `@pgsql/parser` and related packages (`@pgsql/deparser`, `@pgsql/types`) when upgrading major versions. Thoroughly test existing parsing and transformation logic after an upgrade.","message":"Breaking changes occur between major versions of `@pgsql/parser` due to updates in the underlying PostgreSQL parser (libpg-query) and API refinements. For example, changes in AST node structures or function signatures may be introduced to align with new PostgreSQL features or improve consistency.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Utilize helper packages like `@pgsql/utils` for programmatic AST construction and `@pgsql/traverse` for safer traversal and modification via a visitor pattern. Always validate modified ASTs by deparsing and testing the resulting SQL.","message":"Direct manipulation of the PostgreSQL AST can be complex due to its depth and the specific structure reflecting PostgreSQL's internal representation. Incorrect modifications can lead to invalid SQL or runtime errors during deparsing.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Install the package: `npm install @pgsql/parser` or `yarn add @pgsql/parser`.","cause":"The `@pgsql/parser` package has not been installed, or TypeScript cannot resolve it.","error":"Cannot find package '@pgsql/parser' or its corresponding type declarations."},{"fix":"Carefully review the SQL/PL/pgSQL string for typos, missing punctuation, incorrect keywords, or dialect-specific syntax not compatible with standard PostgreSQL. Ensure the `@pgsql/parser` version supports the target PostgreSQL version's syntax.","cause":"The input SQL or PL/pgSQL string contains invalid syntax according to the PostgreSQL grammar, or the parser version used does not support certain syntax.","error":"Syntax error at or near \"...\""},{"fix":"For ESM (`type: 'module'` in package.json or `.mjs` files): `import { parse } from '@pgsql/parser';`. For CommonJS (`type: 'commonjs'` or `.cjs` files): `const { parse } = require('@pgsql/parser');`.","cause":"Attempting to use CommonJS `require` syntax in an ESM module, or vice-versa, or incorrectly accessing the named export `parse`.","error":"TypeError: parse is not a function (or similar for require)"}],"ecosystem":"npm"}