Skip to content

launchql/pgsql-parser

Repository files navigation

pgsql-parser

PostgreSQL Parsing, Deparsing & AST Tools

A comprehensive monorepo for PostgreSQL Abstract Syntax Tree (AST) parsing, manipulation, and code generation. This collection of packages provides everything you need to work with PostgreSQL at the AST level, from parsing SQL queries to generating type-safe TypeScript definitions.

πŸ“¦ Packages

Package Description Key Features
pgsql-parser The real PostgreSQL parser for Node.js β€’ Uses actual PostgreSQL C parser via WebAssembly
β€’ Symmetric parsing and deparsing
β€’ Battle-tested with 23,000+ SQL statements
pgsql-deparser Lightning-fast SQL generation from AST β€’ Pure TypeScript, zero runtime dependencies
β€’ No WebAssembly overhead
β€’ Perfect for AST-to-SQL conversion only
@pgsql/cli Unified CLI for all PostgreSQL AST operations β€’ Parse SQL to AST
β€’ Deparse AST to SQL
β€’ Generate TypeScript from protobuf
β€’ Single tool for all operations
@pgsql/utils Type-safe AST node creation utilities β€’ Programmatic AST construction
β€’ Runtime Schema
β€’ Seamless integration with types
pg-proto-parser PostgreSQL protobuf parser and code generator β€’ Generate TypeScript interfaces from protobuf
β€’ Create enum mappings and utilities
β€’ AST helper generation

πŸš€ Quick Start

Installation

Choose the packages you need:

# For parsing SQL to AST and back (includes deparser)
npm install pgsql-parser

# For only converting AST to SQL (lighter weight)
npm install pgsql-deparser

# For the unified CLI tool
npm install -g @pgsql/cli

# For programmatic AST construction
npm install @pgsql/utils

# For protobuf parsing and code generation
npm install pg-proto-parser

Basic Usage

Parse SQL to AST

import { parse } from 'pgsql-parser';

const ast = await parse('SELECT * FROM users WHERE id = 1');
console.log(JSON.stringify(ast, null, 2));
// {"version":170004,"stmts":[{"stmt":{"SelectStmt":{"targetList":[{"ResTarget": ... ,"op":"SETOP_NONE"}}}]}

Convert AST back to SQL

import { deparse } from 'pgsql-deparser';

const sql = await deparse(ast);
console.log(sql); // SELECT * FROM users WHERE id = 1

Build AST Programmatically

import * as t from '@pgsql/utils';
import { deparse } from 'pgsql-deparser';
import { SelectStmt } from '@pgsql/types';

const stmt: { SelectStmt: SelectStmt } = t.nodes.selectStmt({
  targetList: [
    t.nodes.resTarget({
      val: t.nodes.columnRef({
        fields: [t.nodes.aStar()]
      })
    })
  ],
  fromClause: [
    t.nodes.rangeVar({
      relname: 'some_table',
      inh: true,
      relpersistence: 'p'
    })
  ],
  limitOption: 'LIMIT_OPTION_DEFAULT',
  op: 'SETOP_NONE'
});

await deparse(stmt);

Use the CLI

npm install -g @pgsql/cli

# Parse SQL file
pgsql parse query.sql

# Convert AST to SQL
pgsql deparse ast.json

# Generate TypeScript from protobuf
pgsql proto-gen --inFile pg_query.proto --outDir out --types --enums

πŸ› οΈ Development

This project uses Yarn workspaces and Lerna for monorepo management. See DEVELOPMENT.md for more info.

Setup

# Install dependencies
yarn install

# Build all packages
yarn build

Building Individual Packages

cd packages/parser
npm run build

More Examples

Transform a Query

import { parse } from 'pgsql-parser';
import { deparse } from 'pgsql-deparser';

// Parse the original query
const ast = await parse('SELECT * FROM users WHERE active = true');

// Modify the table name
ast[0].RawStmt.stmt.SelectStmt.fromClause[0].RangeVar.relname = 'customers';

// Generate the modified SQL
const newSql = await deparse(ast);
console.log(newSql); // SELECT * FROM customers WHERE active = TRUE

Build a Query Programmatically

import ast from '@pgsql/utils';
import { deparse } from 'pgsql-deparser';

const query: { SelectStmt: SelectStmt } = t.nodes.selectStmt({
  targetList: [
    t.nodes.resTarget({
      val: t.nodes.columnRef({
        fields: [t.nodes.string({ sval: 'name' })]
      })
    }),
    t.nodes.resTarget({
      val: t.nodes.columnRef({
        fields: [t.nodes.string({ sval: 'email' })]
      })
    })
  ],
  fromClause: [
    t.nodes.rangeVar({
      relname: 'users',
      inh: true,
      relpersistence: 'p'
    })
  ],
  whereClause: t.nodes.aExpr({
    kind: 'AEXPR_OP',
    name: [t.nodes.string({ sval: '>' })],
    lexpr: t.nodes.columnRef({
      fields: [t.nodes.string({ sval: 'age' })]
    }),
    rexpr: t.nodes.aConst({
      ival: t.ast.integer({ ival: 18 })
    })
  }),
  limitOption: 'LIMIT_OPTION_DEFAULT',
  op: 'SETOP_NONE'
});

console.log(await deparse(query));
// SELECT name, email FROM users WHERE age > 18

Related

  • pgsql-parser: The real PostgreSQL parser for Node.js, providing symmetric parsing and deparsing of SQL statements with actual PostgreSQL parser integration.
  • pgsql-deparser: A streamlined tool designed for converting PostgreSQL ASTs back into SQL queries, focusing solely on deparser functionality to complement pgsql-parser.
  • @pgsql/parser: Multi-version PostgreSQL parser with dynamic version selection at runtime, supporting PostgreSQL 15, 16, and 17 in a single package.
  • @pgsql/types: Offers TypeScript type definitions for PostgreSQL AST nodes, facilitating type-safe construction, analysis, and manipulation of ASTs.
  • @pgsql/enums: Provides TypeScript enum definitions for PostgreSQL constants, enabling type-safe usage of PostgreSQL enums and constants in your applications.
  • @pgsql/utils: A comprehensive utility library for PostgreSQL, offering type-safe AST node creation and enum value conversions, simplifying the construction and manipulation of PostgreSQL ASTs.
  • pg-proto-parser: A TypeScript tool that parses PostgreSQL Protocol Buffers definitions to generate TypeScript interfaces, utility functions, and JSON mappings for enums.
  • libpg-query: The real PostgreSQL parser exposed for Node.js, used primarily in pgsql-parser for parsing and deparsing SQL queries.

Disclaimer

AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.

No developer or entity involved in creating Software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the Software code or Software CLI, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.

About

🐘 PostgreSQL Query Parser for Node.js

Resources

License

Stars

Watchers

Forks

Packages

No packages published