Simple SQL parser library that converts SQL statements to AST and back to SQL with support for multiple database engines
npx @tessl/cli install tessl/npm-node-sql-parser@5.3.0Node SQL Parser is a comprehensive SQL parsing library that converts SQL statements into Abstract Syntax Trees (AST) and back to SQL strings. It supports multiple database engines including MySQL, PostgreSQL, SQLite, BigQuery, MariaDB, DB2, Hive, Redshift, TransactSQL, FlinkSQL, Snowflake, and others. The library provides table and column extraction capabilities with authority information, making it ideal for SQL analysis, security checks, and query validation.
npm install node-sql-parserconst { Parser } = require('node-sql-parser');For ES modules:
import { Parser, util } from 'node-sql-parser';For database-specific parsers:
const { Parser } = require('node-sql-parser/build/mysql');
const { Parser } = require('node-sql-parser/build/postgresql');const { Parser } = require('node-sql-parser');
const parser = new Parser();
// Parse SQL to AST
const ast = parser.astify('SELECT * FROM users WHERE age > 18');
// Convert AST back to SQL
const sql = parser.sqlify(ast);
// Get table and column lists with parse()
const { tableList, columnList, ast: parsedAst } = parser.parse(
'SELECT name, email FROM users WHERE active = 1'
);
console.log(tableList); // ["select::null::users"]
console.log(columnList); // ["select::users::name", "select::users::email", "select::users::active"]For browser environments, you can use the UMD builds:
<!-- Full parser (supports all databases, ~750KB) -->
<script src="https://unpkg.com/node-sql-parser/umd/index.umd.js"></script>
<!-- Database-specific parsers (~150KB each) -->
<script src="https://unpkg.com/node-sql-parser/umd/mysql.umd.js"></script>
<script src="https://unpkg.com/node-sql-parser/umd/postgresql.umd.js"></script>The NodeSQLParser object is available on the global window:
// Use in browser
const parser = new NodeSQLParser.Parser();
const ast = parser.astify("SELECT id, name FROM students WHERE age < 18");
console.log(ast);
const sql = parser.sqlify(ast);
console.log(sql);Node SQL Parser is built around several key components:
Core functionality for parsing SQL strings into structured Abstract Syntax Trees and converting AST back to SQL.
class Parser {
constructor();
parse(sql: string, opt?: Option): TableColumnAst;
astify(sql: string, opt?: Option): AST[] | AST;
sqlify(ast: AST[] | AST, opt?: Option): string;
}
interface TableColumnAst {
tableList: string[];
columnList: string[];
ast: AST[] | AST;
loc?: LocationRange;
}
interface Option {
database?: string;
type?: string;
trimQuery?: boolean;
parseOptions?: ParseOptions;
}
interface ParseOptions {
includeLocations?: boolean;
}Specialized functionality for handling SQL expressions, column references, and complex query components.
class Parser {
exprToSQL(expr: any, opt?: Option): string;
columnsToSQL(columns: any, tables: any, opt?: Option): string[];
}Table and column access analysis with whitelist validation for security and authorization checking.
class Parser {
tableList(sql: string, opt?: Option): string[];
columnList(sql: string, opt?: Option): string[];
whiteListCheck(sql: string, whiteList: string[], opt?: Option): Error | undefined;
}
type WhilteListCheckMode = "table" | "column";Helper functions for SQL string manipulation, AST processing, and database-specific formatting.
import { util } from 'node-sql-parser';
// Note: Utility functions are not exported from the main module
// Import directly from the util module for access to these functions
// import { createValueExpr, createBinaryExpr, escape, literalToSQL } from 'node-sql-parser/lib/util';
createValueExpr(value: any): ValueExpr;
createBinaryExpr(operator: string, left: any, right: any): Binary;
escape(str: string): string;
literalToSQL(literal: any): string;
identifierToSql(identifier: string): string;// Core AST Types
type AST = Use | Select | Insert_Replace | Update | Delete | Alter | Create | Drop;
interface Select {
with: With[] | null;
type: "select";
options: any[] | null;
distinct: "DISTINCT" | null;
columns: any[] | Column[];
from: From[] | TableExpr | null;
where: Binary | Function | null;
groupby: { columns: ColumnRef[] | null, modifiers: ValueExpr<string>[] };
having: any[] | null;
orderby: OrderBy[] | null;
limit: Limit | null;
window?: WindowExpr;
qualify?: any[] | null;
loc?: LocationRange;
}
interface Insert_Replace {
type: "replace" | "insert";
table: any;
columns: string[] | null;
values: InsertReplaceValue[] | Select;
partition: any[];
prefix: string;
on_duplicate_update: {
keyword: "on duplicate key update";
set: SetList[];
};
loc?: LocationRange;
returning?: Returning;
}
interface Update {
type: "update";
db: string | null;
table: Array<From | Dual> | null;
set: SetList[];
where: Binary | Function | null;
loc?: LocationRange;
returning?: Returning;
}
interface Delete {
type: "delete";
table: any;
from: Array<From | Dual>;
where: Binary | Function | null;
loc?: LocationRange;
returning?: Returning;
}
// Expression Types
type ExpressionValue = ColumnRef | Param | Function | Case | AggrFunc | Value | Binary | Cast | Interval;
interface Binary {
type: "binary_expr";
operator: string;
left: ExpressionValue | ExprList;
right: ExpressionValue | ExprList;
loc?: LocationRange;
parentheses?: boolean;
}
interface Function {
type: "function";
name: FunctionName;
args?: ExprList;
suffix?: any;
loc?: LocationRange;
}
interface AggrFunc {
type: "aggr_func";
name: string;
args: {
expr: ExpressionValue;
distinct: "DISTINCT" | null;
orderby: OrderBy[] | null;
parentheses?: boolean;
};
loc?: LocationRange;
}
// Table and Column Types
type From = BaseFrom | Join | TableExpr | Dual;
interface BaseFrom {
db: string | null;
table: string;
as: string | null;
schema?: string;
loc?: LocationRange;
}
interface Join extends BaseFrom {
join: "INNER JOIN" | "LEFT JOIN" | "RIGHT JOIN";
using?: string[];
on?: Binary;
}
interface ColumnRef {
type: "column_ref";
table: string | null;
column: string | { expr: ValueExpr };
options?: ExprList;
loc?: LocationRange;
collate?: { collate: CollateExpr } | null;
order_by?: SortDirection | null;
}
// Utility Types
interface ValueExpr<T = string | number | boolean> {
type: "backticks_quote_string" | "string" | "regex_string" | "hex_string" |
"full_hex_string" | "natural_string" | "bit_string" | "double_quote_string" |
"single_quote_string" | "boolean" | "bool" | "null" | "star" | "param" |
"origin" | "date" | "datetime" | "default" | "time" | "timestamp" | "var_string";
value: T;
}
interface OrderBy {
type: "ASC" | "DESC";
expr: any;
loc?: LocationRange;
}
interface Limit {
seperator: string;
value: LimitValue[];
loc?: LocationRange;
}
interface LimitValue {
type: string;
value: number;
loc?: LocationRange;
}Database selection can be specified via options:
const opt = { database: 'PostgreSQL' };
const ast = parser.astify('SELECT * FROM users', opt);
const sql = parser.sqlify(ast, opt);