Added pgSQL support

This commit is contained in:
Salvatore Ravidà 2022-12-15 11:19:46 +01:00 committed by Ziv
parent dea53d45ad
commit a15da8e275
20 changed files with 161798 additions and 1364 deletions

View File

@ -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',

View File

@ -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",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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);
}
}

View 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);
}
}

View 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]);
}
}

View 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;
}
}

View File

@ -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));
parser.program(); // Note : needed by pgsql
if (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
View 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);
}
}

View File

@ -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,

2750
yarn.lock

File diff suppressed because it is too large Load Diff