Postgres SQL AST Parser
pgsql-ast-parser is a JavaScript and TypeScript library designed for parsing PostgreSQL SQL syntax into a typed Abstract Syntax Tree (AST), and then facilitating its modification or conversion back to SQL. It is currently at version 12.0.2 and appears to have an active release cadence, with major versions indicating significant structural changes to the AST. Key differentiators include its ability to run in both Node.js and browser environments, its robust TypeScript typing which is strongly recommended for usage, and its foundational role as the underlying parser for `pg-mem`, an in-memory PostgreSQL database emulator. While it covers most common PostgreSQL syntaxes, it explicitly states it does not support PL/pgSQL or some obscure syntaxes, requiring users to test specific complex queries.
Common errors
-
Syntax Error: Unexpected token at position X
cause The input SQL string contains syntax that the parser does not understand or is malformed.fixReview the SQL query for typos or unsupported features (like PL/pgSQL). Simplify the query or test specific parts to isolate the problematic syntax. If it's standard PostgreSQL syntax, consider opening a bug report. -
Property 'X' does not exist on type 'Y'
cause This TypeScript error occurs when attempting to access a property on an AST node that is either not present on that specific node type or has changed in a breaking library version.fixConsult the library's TypeScript definitions and AST documentation for the specific `pgsql-ast-parser` version you are using. Ensure your code aligns with the current AST structure, especially after major version upgrades. -
require is not defined
cause You are attempting to use CommonJS `require()` to import `pgsql-ast-parser` in an ES module (ESM) environment (e.g., in a file where `type: "module"` is set in `package.json` or a `.mjs` file).fixChange your import statements from `const pkg = require('pgsql-ast-parser');` to `import * as pkg from 'pgsql-ast-parser';` or `import { parse } from 'pgsql-ast-parser';`.
Warnings
- breaking In version 9.0.0, the AST interface for `ALTER TABLE` statements changed. The `change` property was renamed to `changes` and is now an array of `TableAlteration[]`.
- breaking Version 8.0.0 introduced a significant breaking change in how `INSERT` statements are parsed. The `InsertStatement` now has a single `insert` property, unifying the parsing logic for `INSERT ... VALUES` and `INSERT ... SELECT`.
- gotcha The parser does not (yet) support PL/pgSQL or some advanced/funky PostgreSQL syntaxes. Attempting to parse such SQL might result in parsing errors.
- gotcha While usable in JavaScript, the library strongly recommends using TypeScript due to the complexity and depth of the generated Abstract Syntax Tree (AST) types. Without TypeScript, navigating the AST can be prone to errors.
Install
-
npm install pgsql-ast-parser -
yarn add pgsql-ast-parser -
pnpm add pgsql-ast-parser
Imports
- parse, Statement
const { parse, Statement } = require('pgsql-ast-parser');import { parse, Statement } from 'pgsql-ast-parser'; - parseFirst
import parseFirst from 'pgsql-ast-parser';
import { parseFirst } from 'pgsql-ast-parser'; - astVisitor, toSql, astMapper
const astVisitor = require('pgsql-ast-parser').astVisitor;import { astVisitor, toSql, astMapper } from 'pgsql-ast-parser';
Quickstart
import { astVisitor, parseFirst } from 'pgsql-ast-parser';
const tables = new Set<string>();
let joins = 0;
// Create an AST visitor to collect information
const visitor = astVisitor(map => ({
// Hook into table reference nodes to get table names
tableRef: t => tables.add(t.name),
// Hook into join nodes to count joins
join: t => {
joins++;
// Call the default implementation to ensure subtrees are also traversed
map.super().join(t);
}
}));
// Parse a single SQL statement into an AST
const sqlStatement = `SELECT o.order_id, c.customer_name FROM orders AS o LEFT JOIN customers AS c ON o.customer_id = c.customer_id WHERE o.order_date > '2023-01-01';`;
const ast = parseFirst(sqlStatement);
// Start traversing the AST with our visitor
visitor.statement(ast);
// Print the collected results
console.log(`SQL: ${sqlStatement}`);
console.log(`Used tables: ${[...tables].join(', ')}`);
console.log(`Number of joins: ${joins}`);