0.2.0 • Published 4 years ago

ts-mysql-parser v0.2.0

Weekly downloads
145
License
MIT
Repository
github
Last release
4 years ago

ts-mysql-parser

Alt Text

A standalone, grammar-complete MySQL parser.

Alt Text

Features

  • Covers 100% of the MySQL grammar
  • Supports all versions of MySQL
  • Supports multiple statements
  • Supports MySQL mode and character sets
  • Custom lexer and parser listeners

Installation

yarn add ts-mysql-parser
# or
npm install ts-mysql-parser

Usage

import MySQLParser, { SqlMode, MySQLQueryType } from 'ts-mysql-parser'

const parser = new MySQLParser({
  version: '5.7.7',
  mode: SqlMode.AnsiQuotes
})

const result = parser.parse('SELECT id FROM users')

const queryType = parser.getQueryType(result)
console.log(queryType === MySQLQueryType.QtSelect) // true

const tableRef = parser.getNodeAtOffset(result, 18)
console.log(tableRef) // table 'users'

const columnRef = parser.getNodeAtOffset(result, 7)
console.log(columnRef) // column 'id'

API

new MySQLParser(options)

Create a new instance of MySQLParser.

The available options are:

  • version: the MySQL server version (e.g. '5.7.7')
  • mode: the MySQL server mode to run in (e.g. SqlMode.AnsiQuotes)
  • charsets: the MySQL server character sets to support (e.g. [ '_utf8' ])

.parse()

Parse a query.

parser.parse('SELECT id FROM users')

.getQueryType()

Get the query type of the statement.

const result = parser.parse('SELECT id FROM users')
const queryType = parser.getQueryType(parseResult)
console.log(queryType === MySQLQueryType.QtSelect) // true

.getNodeAtOffset()

Get a node in the parse tree at the given offset.

const result = parser.parse('SELECT id FROM users')
const node = parser.getNodeAtOffset(parseResult, 18)
console.log(node) // "users" table

.splitStatements()

Split the text into multiple statements, optionally specifying the line break and delimiter.

parser.splitStatements(`SELECT * from users; SELECT * FROM posts`, '\n', ';')

.getStatementAtOffset()

Get the MySQL statement at the given offset.

const statements = parser.splitStatements(`SELECT * from users; SELECT * FROM posts`, '\n', ';')
const statement = parser.getStatementAtOffset(statements, 30)
console.log(statement) // SELECT * FROM posts

.isKeyword()

Check if the given text is a MySQL keyword.

parser.isKeyword('TIME') // true

.isReservedKeyword()

Check if the given text is a MySQL reserved keyword.

parser.isReservedKeyword('TIME') // false

Using Custom Listeners

You can use your own custom listeners to hook into the parse tree. See examples/custom-parser-listener.ts for an example of how to do this.

Development

When the MySQL grammar changes, we merge in updates to the grammar files, and re-build the lexer and parser by running:

$ yarn build-parser

Afterwards, we need to add the following to the top of src/grammar/MySQLLexer.ts, src/grammar/MySQLParser.ts, and src/grammar/MySQLParserListener.ts:

/* eslint-disable */
// @ts-nocheck

Architecture

This project is built on Antlr4 with the MySQL grammar extracted from MySQL workbench. The grammar itself was kept mostly unchanged, aside from Typescript-specific rule predicates. This allows for easy updating as new versions of MySQL are released.

The MySQLBaseLexer class represents a superclass to the lexer class and customizes lexer functionality, such as emitting multiple tokens per rule. Similarly, the MySQLBaseParser class represents a superclass to the parser class and customizes parser functionality. These superclasses allow us to change the MySQL version, mode, and character sets at runtime.

Related

License

MIT


stevenmiller888.github.io  ·  GitHub @stevenmiller888  ·  Twitter @stevenmiller888