PostgreSQL SQL & PL/pgSQL AST Parser (@pgsql/parser)

0.5.8 · active · verified Sun Apr 19

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.

Common errors

Warnings

Install

Imports

Quickstart

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.

import { parse } from '@pgsql/parser';
import { deparse } from '@pgsql/deparser';
import type { SelectStmt } from '@pgsql/types';

async function processSqlQuery(sql: string) {
  try {
    console.log(`Parsing SQL: ${sql}`);
    // Parse the SQL query into an Abstract Syntax Tree (AST)
    const ast = await parse(sql);
    console.log('Parsed AST (partial):', JSON.stringify(ast.stmts[0]?.stmt, null, 2));

    // Example: Accessing a specific type of statement and its properties
    if (ast.stmts[0]?.stmt.SelectStmt) {
      const selectStmt = ast.stmts[0].stmt.SelectStmt as SelectStmt;
      console.log('Target list items:', selectStmt.targetList?.map(t => JSON.stringify(t.ResTarget?.val)));
    }

    // Convert the AST back to SQL (deparse)
    const deparsedSql = await deparse(ast);
    console.log(`Deparsed SQL: ${deparsedSql}`);

  } catch (error: any) {
    console.error('Error processing SQL:', error.message);
    if (error.sqlDetails) {
      console.error('SQL Details:', error.sqlDetails);
    }
  }
}

// Example SQL queries
processSqlQuery('SELECT id, name FROM users WHERE status = $1 ORDER BY created_at DESC;');
processSqlQuery('CREATE FUNCTION add(a INT, b INT) RETURNS INT LANGUAGE plpgsql AS $$ BEGIN RETURN a + b; END; $$;');
// Intentionally malformed SQL to demonstrate error handling
// processSqlQuery('SELECT * FROM users WHERE;');

view raw JSON →