node-sql-parser

Parses SQL statements into an AST and converts them back to SQL across a dozen database dialects.

Library
npm
v5.4.0
1,043 stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
57 /100 Fair
Development Activity 16
Maintenance 32
Community 80
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
68 /100 Good
Architecture 75
Code Quality 68
Innovation 72
Learning Curve 55

node-sql-parser is a pure JavaScript SQL parser that turns SQL statements into an abstract syntax tree (AST) and can convert that AST back into SQL. It ships dialect-specific grammars for MySQL, PostgreSQL, MariaDB, Sqlite, TransactSQL, BigQuery, Athena, Redshift, Hive, DB2, FlinkSQL, Snowflake, Trino, and a generic Noql variant, each compiled from its own PEG.js grammar file in the pegjs/ directory.

Beyond producing an AST, the library extracts the table list and column list a query touches, tagged with the operation type (select/update/delete/insert), which makes it useful for building SQL-based authorization checks (whiteListCheck), lineage tools, or query linters without writing a parser from scratch.

What You Get

  • Dialect-specific parsers for MySQL, PostgreSQL, MariaDB, Sqlite, TransactSQL, BigQuery, Athena, Redshift, Hive, DB2, FlinkSQL, Snowflake, Trino, and Noql, each importable individually to keep bundle size down.
  • A Parser class exposing astify, sqlify, parse, tableList, columnList, and whiteListCheck methods.
  • Full AST round-tripping - parse SQL to a JSON AST and re-serialize it back to valid SQL for the target dialect.
  • Table- and column-level authority lists tagged by operation (select/update/delete/insert) for query auditing.
  • TypeScript type definitions (types.d.ts) and a browser-ready UMD bundle (about 750KB full, about 150KB per-dialect) distributed via unpkg.

Common Use Cases

  • Building SQL query linters or style checkers that need a real AST rather than regex matching.
  • Enforcing table/column-level access control by whitelisting which tables and columns a query is allowed to touch.
  • Extracting table and column lineage from application SQL for data-governance or impact-analysis tooling.
  • Translating or normalizing SQL between dialects (e.g. rewriting MySQL queries for PostgreSQL) via astify/sqlify round-trips.

Under The Hood

Architecture

PEG.js grammar files (pegjs/*.pegjs, one per dialect plus shared fragments under pegjs/common/) are compiled by gulp tasks (gulp render, gulp generate) into JS parser modules under lib/parser/{dialect}.js, which src/parser.all.js imports and exposes as a flat map keyed by dialect name. The public Parser class in src/parser.js is a thin facade: parse() looks up the grammar-generated parser function by opt.database, astify()/sqlify() delegate AST creation to the grammar and reserialization to src/sql.js’s astToSQL, and tableList/columnList/whiteListCheck build authority strings off that same AST. AST-to-SQL conversion is itself split per node kind (src/column.js, src/expr.js, src/binary.js, src/select.js, src/create.js, and more), each owning one grammar production. The core abstraction every dialect depends on is the AST shape itself, so adding a new dialect means writing a grammar that still emits AST nodes the shared converters can consume; changing that shape would ripple through every converter file and every grammar.

Tech Stack

Parsing runs on peggy (the PEG.js successor), with grammars pre-compiled at build time via gulp; the JS source is transpiled with Babel and bundled for the browser with Webpack 4 plus webpack-node-externals and tinyify. TypeScript types ship as a hand-maintained types.d.ts rather than being generated from typed source (only a couple of files under ast/ and plugins/ are actual TypeScript). The library carries a single runtime dependency, big-integer, for handling large integer literals in SQL, and is packaged for both CommonJS and UMD (browser, via unpkg) consumption. There is no network or database I/O anywhere in the library - it is a pure text-in, AST-out parser.

Code Quality

Tests live under test/*.spec.js (24 spec files covering per-dialect syntax plus dedicated select/insert/update/delete/create/ast suites), run with mocha via mochapack and asserted with chai, with coverage collected through nyc/istanbul and reported to Coveralls. CI (a GitHub Actions workflow, plus a legacy Travis config) runs lint plus the full grammar build plus the test suite before any release. Linting uses ESLint with airbnb-base and strict configs enforcing rules like comma-dangle, eqeqeq, and no-var. Error handling is explicit rather than swallowed - parse() throws a plain Error for an unsupported dialect and whiteListCheck throws with a descriptive deny message. Type safety inside src/ itself is JavaScript-level only; the shipped .d.ts is maintained separately from the implementation.

API Design The public surface is small and consistent: const { Parser } = require('node-sql-parser'); const parser = new Parser() covers astify, sqlify, tableList, columnList, and whiteListCheck with the same options object ({ database, type, parseOptions }) accepted everywhere, and no configuration is required to parse MySQL (the default) out of the box. Per-dialect imports (node-sql-parser/build/{database}) trade bundle size for the same API shape rather than a different one. The README documents every method with a runnable, copy-pasteable example, including the browser/UMD path. The main rough edges are terse error messages for unsupported dialects and a manually maintained type-definitions file that can drift from the actual runtime implementation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers