Added pgSQL support
This commit is contained in:
parent
dea53d45ad
commit
a15da8e275
@ -8,6 +8,7 @@ const output = path.resolve(__dirname, '../src/lib');
|
|||||||
const entry = [
|
const entry = [
|
||||||
'generic',
|
'generic',
|
||||||
'hive',
|
'hive',
|
||||||
|
'pgsql',
|
||||||
'plsql',
|
'plsql',
|
||||||
'spark',
|
'spark',
|
||||||
'flinksql',
|
'flinksql',
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
"eslint-config-google": "^0.14.0",
|
"eslint-config-google": "^0.14.0",
|
||||||
"jest": "^24.8.0",
|
"jest": "^24.8.0",
|
||||||
"ts-jest": "^24.1.0",
|
"ts-jest": "^24.1.0",
|
||||||
"typescript": "^3.6.3",
|
"typescript": "^4.9.4",
|
||||||
"standard-version": "^9.1.0"
|
"standard-version": "^9.1.0"
|
||||||
},
|
},
|
||||||
"git repository": "https://github.com/DTStack/dt-sql-parser",
|
"git repository": "https://github.com/DTStack/dt-sql-parser",
|
||||||
|
2544
src/grammar/pgsql/PostgreSQLLexer.g4
Normal file
2544
src/grammar/pgsql/PostgreSQLLexer.g4
Normal file
File diff suppressed because it is too large
Load Diff
5327
src/grammar/pgsql/PostgreSQLParser.g4
Normal file
5327
src/grammar/pgsql/PostgreSQLParser.g4
Normal file
File diff suppressed because it is too large
Load Diff
1702
src/lib/pgsql/PostgreSQLLexer.interp
Normal file
1702
src/lib/pgsql/PostgreSQLLexer.interp
Normal file
File diff suppressed because one or more lines are too long
4873
src/lib/pgsql/PostgreSQLLexer.js
Normal file
4873
src/lib/pgsql/PostgreSQLLexer.js
Normal file
File diff suppressed because it is too large
Load Diff
1066
src/lib/pgsql/PostgreSQLLexer.tokens
Normal file
1066
src/lib/pgsql/PostgreSQLLexer.tokens
Normal file
File diff suppressed because it is too large
Load Diff
1925
src/lib/pgsql/PostgreSQLParser.interp
Normal file
1925
src/lib/pgsql/PostgreSQLParser.interp
Normal file
File diff suppressed because one or more lines are too long
129402
src/lib/pgsql/PostgreSQLParser.js
Normal file
129402
src/lib/pgsql/PostgreSQLParser.js
Normal file
File diff suppressed because one or more lines are too long
1066
src/lib/pgsql/PostgreSQLParser.tokens
Normal file
1066
src/lib/pgsql/PostgreSQLParser.tokens
Normal file
File diff suppressed because it is too large
Load Diff
7305
src/lib/pgsql/PostgreSQLParserListener.js
Normal file
7305
src/lib/pgsql/PostgreSQLParserListener.js
Normal file
File diff suppressed because it is too large
Load Diff
4876
src/lib/pgsql/PostgreSQLParserVisitor.js
Normal file
4876
src/lib/pgsql/PostgreSQLParserVisitor.js
Normal file
File diff suppressed because it is too large
Load Diff
55
src/lib/pgsql/base/LexerDispatchingErrorListener.java
Normal file
55
src/lib/pgsql/base/LexerDispatchingErrorListener.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import java.util.BitSet;
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
import org.antlr.v4.runtime.atn.*;
|
||||||
|
import org.antlr.v4.runtime.dfa.*;
|
||||||
|
import org.antlr.v4.runtime.misc.*;
|
||||||
|
|
||||||
|
public class LexerDispatchingErrorListener implements ANTLRErrorListener
|
||||||
|
{
|
||||||
|
Lexer _parent;
|
||||||
|
|
||||||
|
public LexerDispatchingErrorListener(Lexer parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
|
||||||
|
{
|
||||||
|
var foo = new ProxyErrorListener(_parent.getErrorListeners());
|
||||||
|
foo.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportAmbiguity(Parser recognizer,
|
||||||
|
DFA dfa,
|
||||||
|
int startIndex,
|
||||||
|
int stopIndex,
|
||||||
|
boolean exact,
|
||||||
|
BitSet ambigAlts,
|
||||||
|
ATNConfigSet configs)
|
||||||
|
{
|
||||||
|
var foo = new ProxyErrorListener(_parent.getErrorListeners());
|
||||||
|
foo.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportAttemptingFullContext(Parser recognizer,
|
||||||
|
DFA dfa,
|
||||||
|
int startIndex,
|
||||||
|
int stopIndex,
|
||||||
|
BitSet conflictingAlts,
|
||||||
|
ATNConfigSet configs)
|
||||||
|
{
|
||||||
|
var foo = new ProxyErrorListener(_parent.getErrorListeners());
|
||||||
|
foo.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportContextSensitivity(Parser recognizer,
|
||||||
|
DFA dfa,
|
||||||
|
int startIndex,
|
||||||
|
int stopIndex,
|
||||||
|
int prediction,
|
||||||
|
ATNConfigSet configs)
|
||||||
|
{
|
||||||
|
var foo = new ProxyErrorListener(_parent.getErrorListeners());
|
||||||
|
foo.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs);
|
||||||
|
}
|
||||||
|
}
|
55
src/lib/pgsql/base/ParserDispatchingErrorListener.java
Normal file
55
src/lib/pgsql/base/ParserDispatchingErrorListener.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import java.util.BitSet;
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
import org.antlr.v4.runtime.atn.*;
|
||||||
|
import org.antlr.v4.runtime.dfa.*;
|
||||||
|
import org.antlr.v4.runtime.misc.*;
|
||||||
|
|
||||||
|
public class ParserDispatchingErrorListener implements ANTLRErrorListener
|
||||||
|
{
|
||||||
|
Parser _parent;
|
||||||
|
|
||||||
|
public ParserDispatchingErrorListener(Parser parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
|
||||||
|
{
|
||||||
|
var foo = new ProxyErrorListener(_parent.getErrorListeners());
|
||||||
|
foo.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportAmbiguity(Parser recognizer,
|
||||||
|
DFA dfa,
|
||||||
|
int startIndex,
|
||||||
|
int stopIndex,
|
||||||
|
boolean exact,
|
||||||
|
BitSet ambigAlts,
|
||||||
|
ATNConfigSet configs)
|
||||||
|
{
|
||||||
|
var foo = new ProxyErrorListener(_parent.getErrorListeners());
|
||||||
|
foo.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportAttemptingFullContext(Parser recognizer,
|
||||||
|
DFA dfa,
|
||||||
|
int startIndex,
|
||||||
|
int stopIndex,
|
||||||
|
BitSet conflictingAlts,
|
||||||
|
ATNConfigSet configs)
|
||||||
|
{
|
||||||
|
var foo = new ProxyErrorListener(_parent.getErrorListeners());
|
||||||
|
foo.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportContextSensitivity(Parser recognizer,
|
||||||
|
DFA dfa,
|
||||||
|
int startIndex,
|
||||||
|
int stopIndex,
|
||||||
|
int prediction,
|
||||||
|
ATNConfigSet configs)
|
||||||
|
{
|
||||||
|
var foo = new ProxyErrorListener(_parent.getErrorListeners());
|
||||||
|
foo.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs);
|
||||||
|
}
|
||||||
|
}
|
67
src/lib/pgsql/base/PostgreSQLLexerBase.js
Normal file
67
src/lib/pgsql/base/PostgreSQLLexerBase.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
const antlr4 = require('antlr4/index');
|
||||||
|
const Lexer = antlr4.Lexer;
|
||||||
|
function isLetter(str) {
|
||||||
|
return str.length === 1 && str.match(/[a-z]/i);
|
||||||
|
}
|
||||||
|
export class PostgreSQLLexerBase extends Lexer {
|
||||||
|
tags = [];
|
||||||
|
|
||||||
|
constructor(input) {
|
||||||
|
super(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
pushTag() {
|
||||||
|
this.tags.push(getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
isTag() {
|
||||||
|
return this.getText().equals(this.tags.peek());
|
||||||
|
}
|
||||||
|
|
||||||
|
popTag() {
|
||||||
|
tags.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
getInputStream() {
|
||||||
|
return this._input;
|
||||||
|
}
|
||||||
|
checkLA( c) {
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
return this.getInputStream().LA(1) !== c;
|
||||||
|
}
|
||||||
|
|
||||||
|
charIsLetter() {
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
return isLetter(this.getInputStream().LA(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleNumericFail() {
|
||||||
|
this.getInputStream().seek(this.getInputStream().index() - 2);
|
||||||
|
const Integral = 535;
|
||||||
|
this.setType(Integral);
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleLessLessGreaterGreater() {
|
||||||
|
const LESS_LESS = 18;
|
||||||
|
const GREATER_GREATER = 19;
|
||||||
|
if (this.getText() === '<<') this.setType(LESS_LESS);
|
||||||
|
if (this.getText() === '>>') this.setType(GREATER_GREATER);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnterminatedBlockCommentDebugAssert() {
|
||||||
|
// Debug.Assert(InputStream.LA(1) == -1 /*EOF*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckIfUtf32Letter() {
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
let codePoint = this.getInputStream().LA(-2) << 8 + this.getInputStream().LA(-1);
|
||||||
|
let c;
|
||||||
|
if (codePoint < 0x10000) {
|
||||||
|
c = String.fromCharCode(codePoint);
|
||||||
|
} else {
|
||||||
|
codePoint -= 0x10000;
|
||||||
|
c = String.fromCharCode(codePoint / 0x400 + 0xd800, codePoint % 0x400 + 0xdc00);
|
||||||
|
}
|
||||||
|
return isLetter(c[0]);
|
||||||
|
}
|
||||||
|
}
|
114
src/lib/pgsql/base/PostgreSQLParserBase.js
Normal file
114
src/lib/pgsql/base/PostgreSQLParserBase.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* eslint-disable new-cap */
|
||||||
|
import { PostgreSQLLexer } from '../PostgreSQLLexer';
|
||||||
|
import { PostgreSQLParser } from '../PostgreSQLParser';
|
||||||
|
|
||||||
|
|
||||||
|
const antlr4 = require('antlr4/index');
|
||||||
|
const CharStreams = antlr4.CharStreams;
|
||||||
|
const CommonTokenStream = antlr4.CommonTokenStream;
|
||||||
|
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
export class PostgreSQLParserBase extends antlr4.Parser {
|
||||||
|
constructor( input) {
|
||||||
|
super(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
GetParsedSqlTree( script, line) {
|
||||||
|
const ph = this.getPostgreSQLParser(script);
|
||||||
|
return ph.root();
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseRoutineBody( _localctx) {
|
||||||
|
let lang = null;
|
||||||
|
for (const coi of _localctx.createfunc_opt_item()) {
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
if (!coi.LANGUAGE()) {
|
||||||
|
if (!coi.nonreservedword_or_sconst()) {
|
||||||
|
if (!coi.nonreservedword_or_sconst().nonreservedword()) {
|
||||||
|
if (!coi.nonreservedword_or_sconst().nonreservedword().identifier()) {
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
if (!coi.nonreservedword_or_sconst().nonreservedword().identifier().Identifier()) {
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
lang = coi.nonreservedword_or_sconst().nonreservedword().identifier().Identifier().getText();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!lang) return;
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
let func_as = null;
|
||||||
|
for (const a of _localctx.createfunc_opt_item()) {
|
||||||
|
if (!a.func_as()) {
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
func_as = a;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
if (!func_as) {
|
||||||
|
const txt = this.GetRoutineBodyString(func_as.func_as().sconst(0));
|
||||||
|
const line = func_as.func_as().sconst(0).start.getLine();
|
||||||
|
const ph = this.getPostgreSQLParser(txt);
|
||||||
|
switch (lang) {
|
||||||
|
case 'plpgsql':
|
||||||
|
func_as.func_as().Definition = ph.plsqlroot();
|
||||||
|
break;
|
||||||
|
case 'sql':
|
||||||
|
func_as.func_as().Definition = ph.root();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TrimQuotes( s) {
|
||||||
|
return (!s) ? s : s.substring(1, s.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unquote( s) {
|
||||||
|
const slength = s.length();
|
||||||
|
const r = '';
|
||||||
|
let i = 0;
|
||||||
|
while (i < slength) {
|
||||||
|
const c = s.charAt(i);
|
||||||
|
r.append(c);
|
||||||
|
if (c === '\'' && i < slength - 1 && (s.charAt(i + 1) === '\'')) i++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return r.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
GetRoutineBodyString( rule) {
|
||||||
|
const anysconst = rule.anysconst();
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
const StringConstant = anysconst.StringConstant();
|
||||||
|
if (null !== StringConstant) return this.unquote(this.TrimQuotes(StringConstant.getText()));
|
||||||
|
const UnicodeEscapeStringConstant = anysconst.UnicodeEscapeStringConstant();
|
||||||
|
if (null !== UnicodeEscapeStringConstant) return this.TrimQuotes(UnicodeEscapeStringConstant.getText());
|
||||||
|
const EscapeStringConstant = anysconst.EscapeStringConstant();
|
||||||
|
if (null !== EscapeStringConstant) return this.TrimQuotes(EscapeStringConstant.getText());
|
||||||
|
let result = '';
|
||||||
|
const dollartext = anysconst.DollarText();
|
||||||
|
for (const s of dollartext) {
|
||||||
|
result += s.getText();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getPostgreSQLParser( script) {
|
||||||
|
const charStream = CharStreams.fromString(script);
|
||||||
|
const lexer = new PostgreSQLLexer(charStream);
|
||||||
|
const tokens = new CommonTokenStream(lexer);
|
||||||
|
const parser = new PostgreSQLParser(tokens);
|
||||||
|
lexer.removeErrorListeners();
|
||||||
|
parser.removeErrorListeners();
|
||||||
|
// LexerDispatchingErrorListener listener_lexer = new LexerDispatchingErrorListener((Lexer)(((CommonTokenStream)(this.getInputStream())).getTokenSource()));
|
||||||
|
// ParserDispatchingErrorListener listener_parser = new ParserDispatchingErrorListener(this);
|
||||||
|
// lexer.addErrorListener(listener_lexer);
|
||||||
|
// parser.addErrorListener(listener_parser);
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,8 @@ export default abstract class BasicParser<C = any> {
|
|||||||
parser.removeErrorListeners();
|
parser.removeErrorListeners();
|
||||||
parser.addErrorListener(new ParserErrorListener(errorListener));
|
parser.addErrorListener(new ParserErrorListener(errorListener));
|
||||||
|
|
||||||
const parserTree = parser.program();
|
// Note : needed by pgsql
|
||||||
|
const parserTree = parser.program? parser.program() : parser.root();
|
||||||
|
|
||||||
return parserTree;
|
return parserTree;
|
||||||
}
|
}
|
||||||
@ -37,7 +38,12 @@ export default abstract class BasicParser<C = any> {
|
|||||||
parser.removeErrorListeners();
|
parser.removeErrorListeners();
|
||||||
parser.addErrorListener(new ParserErrorCollector(syntaxErrors));
|
parser.addErrorListener(new ParserErrorCollector(syntaxErrors));
|
||||||
|
|
||||||
|
// Note : needed by pgsql
|
||||||
|
if (parser.program) {
|
||||||
parser.program();
|
parser.program();
|
||||||
|
} else {
|
||||||
|
parser.root();
|
||||||
|
}
|
||||||
|
|
||||||
return lexerError.concat(syntaxErrors);
|
return lexerError.concat(syntaxErrors);
|
||||||
}
|
}
|
||||||
@ -89,7 +95,8 @@ export default abstract class BasicParser<C = any> {
|
|||||||
const parser = this.createParser(input);
|
const parser = this.createParser(input);
|
||||||
this._parser = parser;
|
this._parser = parser;
|
||||||
|
|
||||||
const tree = parser.program();
|
// Note : needed by pgsql
|
||||||
|
const tree = parser.program? parser.program() : parser.root();
|
||||||
return tree.toStringTree(parser.ruleNames);
|
return tree.toStringTree(parser.ruleNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
src/parser/pgsql.ts
Normal file
17
src/parser/pgsql.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { InputStream, CommonTokenStream, Lexer } from 'antlr4';
|
||||||
|
import { PostgreSQLLexer } from '../lib/pgsql/PostgreSQLLexer';
|
||||||
|
import { PostgreSQLParser } from '../lib/pgsql/PostgreSQLParser';
|
||||||
|
|
||||||
|
import BasicParser from './common/basicParser';
|
||||||
|
|
||||||
|
export default class PLSQLParser extends BasicParser {
|
||||||
|
public createLexer(input: string): Lexer {
|
||||||
|
const chars = new InputStream(input.toUpperCase());
|
||||||
|
const lexer = <unknown> new PostgreSQLLexer(chars) as Lexer;
|
||||||
|
return lexer;
|
||||||
|
}
|
||||||
|
public createParserFromLexer(lexer: Lexer): any {
|
||||||
|
const tokenStream = new CommonTokenStream(lexer);
|
||||||
|
return new PostgreSQLParser(tokenStream);
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
"outDir": "./dist/",
|
"outDir": "./dist/",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"allowJs":true,
|
"allowJs":true,
|
||||||
"target": "es6",
|
"target": "es5",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user