# node-sql-parser: SQL to AST and back, with the tables it touched

> node-sql-parser is a PEG.js based SQL parser for JavaScript that turns a statement into an abstract syntax tree, converts that tree back into SQL, and reports which tables and columns the statement visited with the corresponding authority. It covers a dozen database dialects, runs in Node or in a browser, and the dialect you get by default is MySQL unless you say otherwise.

**taozhi8833998/node-sql-parser** — Parse simple SQL statements into an abstract syntax tree (AST) with the visited tableList and convert it back to SQL

- Repository: https://github.com/taozhi8833998/node-sql-parser
- Website: https://taozhi8833998.github.io/node-sql-parser/
- Stars: 1,043 · Forks: 246
- Language: PEG.js
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/taozhi8833998-node-sql-parser

## What the library actually gives you back

The project description is the whole pitch, and it has three parts. It parses SQL statements into an abstract syntax tree, it reports the table list and column list the statement visited, and it converts the tree back into SQL. The first and third are the familiar round trip that any parser library offers. The middle one is the part that earns the library its place, and the feature list spells out that the output is the table and column list with the corresponding authority, which is the information you need when you are deciding whether a query is allowed, whether it is expensive, or whether a rewrite changed what it touches. The supported statement types are listed too, select, delete, update and insert, plus drop, truncate and rename, and multiple statements separated by semicolons are supported, so a script of SQL can be parsed in one pass rather than one statement at a time. The README also notes support for various database engines, which is where most of the real work of such a library lives.

## Twelve dialects, and two ways to pick the wrong one

The supported dialect list is long: Athena, BigQuery, DB2, Hive, MariaDB, MySQL, PostgreSQL, Redshift, Sqlite, TransactSQL, FlinkSQL, Snowflake which is marked as alpha, and Noql, with a note that an issue can be opened for other databases. There are two ways to select one, and the difference is a bundle size decision as much as an API one. The first is to import the parser for the database you need from a specific path, for example `require('node-sql-parser/build/transactsql')`, which is how you keep only the grammar you need in your bundle. The second is to import the general Parser and pass an options object with a `database` property, for example `Postgresql`. The trap here is the default. The examples show that MySQL is the default grammar when you call `astify` with no options, and the round trip output differs by dialect in ways that are visible, with MySQL producing backticks around the table name and the TransactSQL build producing square brackets. A parser that silently applies the wrong dialect will give you an AST that looks plausible and a regenerated query that is wrong.

## The AST shape, and asking for source locations

The AST is a plain JSON object with one key per clause of the statement, and the README shows the shape for a minimal query. The top level has `with`, `type`, `options`, `distinct`, `columns`, `from`, `where`, `groupby`, `having`, `orderby` and `limit`, with the `type` set to `select` and the `from` an array of objects holding the database, the table and the alias. That is an easy shape to work with, because a caller that only needs the table names can read one array and ignore the rest. 

```javascript
const { Parser } = require('node-sql-parser');
const parser = new Parser();
const ast = parser.astify('SELECT * FROM t');
const sql = parser.sqlify(ast);
```

The library also has an option to attach source positions, by passing `parseOptions: { includeLocations: true }` to `astify`, and the result then carries a `loc` property with start and end offsets, line numbers and column numbers on the nodes that were matched. That is what you need to map a finding in a parsed statement back to a line in a file, which is the difference between a parser you use in a linter and one you use in a report.

## Going back to SQL, and what the round trip preserves

The reverse direction is `sqlify`, and the README's example shows the round trip with the same options object used for parsing. The input is an AST, the output is a SQL string, and the interesting detail is that the regenerated SQL is not a textual copy of the original. The parsed example is `SELECT * FROM t` and the regenerated string is `SELECT * FROM \`t\``, with the table name quoted the way MySQL quotes it, and the TransactSQL build of the same statement produces `SELECT [id] FROM [test] AS [result]`. So the round trip normalises the statement into the target dialect's conventions, which is exactly what you want if you are rewriting a query, and exactly what you do not want if you are trying to diff a statement against the original text. The AST, rather than the string, is the stable representation to work with.

## The build is a grammar pipeline, and the pre-commit hook runs coverage

The repository layout shows how the parsers are produced, and it is a generated-code project rather than a hand written one. The grammars live in a `pegjs/` directory, the build steps are `npm run build:pegjs`, which runs a gulp render and a gulp generate, followed by a webpack build, and there is a separate `compile` script that runs babel over `src` into `lib`. The generated grammars are committed, since the published files list includes `ast/`, `build`, `lib` and `umd/`. The test setup is unusual in a way worth knowing, because the pre-commit hook runs `coverLocal`, which builds the grammars, runs the coverage instrumentation and produces a report, so a commit is gated on the coverage suite passing rather than only on lint. The test runner itself is mochapack with a large diff size option, which is what you need for AST snapshots, and the `cover` script pipes the nyc output into coveralls. The release script builds and publishes from an `output/prod` directory, so the published artifact is the production webpack bundle rather than the source tree.

## Three ways to install it, and the browser bundle sizes

Installation is unremarkable from npm, with `npm install node-sql-parser --save` or `yarn add node-sql-parser`, and there is a second route through the GitHub Package Registry for consumers inside an organisation, using the scoped package name with the registry flag. The third route is the browser, and the README is honest about the cost. The UMD build with every database parser is about 750K, and you can instead import a single dialect build at about 150K, with script tags shown for the MySQL and PostgreSQL builds. In the browser the entry point is a `NodeSQLParser` object placed on `window`, and the README includes a complete HTML example that constructs `new NodeSQLParser.Parser()`, calls `astify` on a query, logs the AST and then calls `sqlify` and logs the SQL. The package also publishes type definitions, with a badge pointing at the DefinitelyTyped entry, and the `types` field in the manifest points at a `types.d.ts` that the repository generates with a `typegen.js` script.

## Scope, versions and what to watch

The scope is bounded in a way that matters for evaluation. The project describes itself as a simple SQL parser, and the supported statement types are the common ones, so procedural SQL, window functions beyond what the grammar covers, and vendor specific extensions are where you will find the edges. The dialect list has one entry explicitly marked alpha, Snowflake, and the README invites an issue for a database that is not listed, which is the normal way this kind of coverage grows. The version history is steady, with 5.3.12 in September 2025, 5.3.13 in October 2025 and 5.4.0 in January 2026, and the last push on the branch was on 2026-07-19, so the project is maintained on a regular release rhythm rather than continuously. The licence is Apache-2.0, the homepage hosts the documentation, and the practical advice for a new user is to parse with an explicit dialect option, work with the AST rather than the regenerated string, and turn on the location information if you intend to report anything back to a user.

## Conclusion

Adopt node-sql-parser if you need to inspect, rewrite, audit or lint SQL in JavaScript, especially if you need the list of tables and columns a statement touches, because that is the feature the project is built around. Do not expect it to be a full SQL engine, since the description scopes it to simple statements, and pin the dialect explicitly in every call, because the default is MySQL and a Postgres query parsed as MySQL will give you an AST that does not match your database. Before you build on it, check the supported dialect list for your database, where Snowflake is still marked alpha, and decide whether you want the full bundle or a single dialect build, since the browser UMD build with every parser is around 750K against roughly 150K for one. The licence is Apache-2.0, the current release is 5.4.0 from 2026-01-12, and the last push was on 2026-07-19.

## FAQ

### Which SQL dialects does node-sql-parser support?

Athena, BigQuery, DB2, Hive, MariaDB, MySQL, PostgreSQL, Redshift, Sqlite, TransactSQL, FlinkSQL, Snowflake, which is marked alpha, and Noql. MySQL is the default grammar when you do not pass a database option.

### How do I get the tables and columns a query uses?

The parser reports the table list and column list the statement visited with the corresponding authority, and the AST exposes them directly, with the `from` array holding the database, table and alias for each source. That is the feature the project is built around.

### Can node-sql-parser tell me where in the source a clause was?

Yes, by passing `parseOptions: { includeLocations: true }` to `astify`, which attaches a `loc` property to the matched nodes with start and end offsets, line numbers and column numbers.

### How do I convert the AST back into SQL?

Call `parser.sqlify(ast, opt)` with the same options object used for parsing. The output is normalised to the target dialect's quoting conventions, for example backticks for MySQL and square brackets for TransactSQL, so the regenerated string is not a textual copy of the original.

## Sources

- [License: Apache-2.0](https://github.com/taozhi8833998/node-sql-parser/blob/master/LICENSE)
- [Project website](https://taozhi8833998.github.io/node-sql-parser/)
- [README](https://github.com/taozhi8833998/node-sql-parser/blob/master/README.md)
- [Releases](https://github.com/taozhi8833998/node-sql-parser/releases)
- [taozhi8833998/node-sql-parser on GitHub](https://github.com/taozhi8833998/node-sql-parser)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/taozhi8833998-node-sql-parser
