refactor: migrate antlr4 v4.12.0 to antlr4ts(4.9.0) (#106)
* build: ignore gen folder * refactor: remove useless code * fix: correct the Javascript usage in grammar * refactor: move to antlr4ts * fix: remove useless * fix: update grammars for javascript target * refactor: migrate to antlr4ts * refactor: migrate to antlr4ts * refactor: implements ParserErrorListener * fix: rename the start reserved word * refactor: remove unused import * refactor: migrate to antlr4ts * test: update the expects of test cases * refactor: migrate hive to antlr4ts * refactor: update the incompatible syntax for antlr4ts * refactor: migrate pgsql grammar to antlr4ts, increasing tests * refactor: migrate the plsql to antlr4ts * build: remove unused config * build: migrate to antlr4ts * build: migrate ts-jest to @swc/jest * refactor: migrate to anltr4ts * build: migrate ts-jest to @swc/jest
This commit is contained in:
244
test/parser/pgsql/fixtures/select.sql
Normal file
244
test/parser/pgsql/fixtures/select.sql
Normal file
@ -0,0 +1,244 @@
|
||||
|
||||
SELECT * FROM onek
|
||||
WHERE onek.unique1 < 10
|
||||
ORDER BY onek.unique1;
|
||||
|
||||
SELECT onek.unique1, onek.stringu1 FROM onek
|
||||
WHERE onek.unique1 < 20
|
||||
ORDER BY unique1 using >;
|
||||
|
||||
SELECT onek.unique1, onek.stringu1 FROM onek
|
||||
WHERE onek.unique1 > 980
|
||||
ORDER BY stringu1 using <;
|
||||
|
||||
SELECT onek.unique1, onek.string4 FROM onek
|
||||
WHERE onek.unique1 > 980
|
||||
ORDER BY string4 using <, unique1 using >;
|
||||
|
||||
SELECT onek.unique1, onek.string4 FROM onek
|
||||
WHERE onek.unique1 > 980
|
||||
ORDER BY string4 using >, unique1 using <;
|
||||
|
||||
--
|
||||
-- awk '{if($1<20){print $1,$16;}else{next;}}' onek.data |
|
||||
-- sort +0nr -1 +1d -2
|
||||
--
|
||||
SELECT onek.unique1, onek.string4 FROM onek
|
||||
WHERE onek.unique1 < 20
|
||||
ORDER BY unique1 using >, string4 using <;
|
||||
|
||||
--
|
||||
-- awk '{if($1<20){print $1,$16;}else{next;}}' onek.data |
|
||||
-- sort +0n -1 +1dr -2
|
||||
--
|
||||
SELECT onek.unique1, onek.string4 FROM onek
|
||||
WHERE onek.unique1 < 20
|
||||
ORDER BY unique1 using <, string4 using >;
|
||||
|
||||
--
|
||||
-- test partial btree indexes
|
||||
--
|
||||
-- As of 7.2, planner probably won't pick an indexscan without stats,
|
||||
-- so ANALYZE first. Also, we want to prevent it from picking a bitmapscan
|
||||
-- followed by sort, because that could hide index ordering problems.
|
||||
--
|
||||
ANALYZE onek2;
|
||||
|
||||
SET enable_seqscan TO off;
|
||||
SET enable_bitmapscan TO off;
|
||||
SET enable_sort TO off;
|
||||
|
||||
--
|
||||
-- awk '{if($1<10){print $0;}else{next;}}' onek.data | sort +0n -1
|
||||
--
|
||||
SELECT onek2.* FROM onek2 WHERE onek2.unique1 < 10;
|
||||
|
||||
--
|
||||
-- awk '{if($1<20){print $1,$14;}else{next;}}' onek.data | sort +0nr -1
|
||||
--
|
||||
SELECT onek2.unique1, onek2.stringu1 FROM onek2
|
||||
WHERE onek2.unique1 < 20
|
||||
ORDER BY unique1 using >;
|
||||
|
||||
--
|
||||
-- awk '{if($1>980){print $1,$14;}else{next;}}' onek.data | sort +1d -2
|
||||
--
|
||||
SELECT onek2.unique1, onek2.stringu1 FROM onek2
|
||||
WHERE onek2.unique1 > 980;
|
||||
|
||||
RESET enable_seqscan;
|
||||
RESET enable_bitmapscan;
|
||||
RESET enable_sort;
|
||||
|
||||
|
||||
SELECT two, stringu1, ten, string4
|
||||
INTO TABLE tmp
|
||||
FROM onek;
|
||||
|
||||
--
|
||||
-- awk '{print $1,$2;}' person.data |
|
||||
-- awk '{if(NF!=2){print $3,$2;}else{print;}}' - emp.data |
|
||||
-- awk '{if(NF!=2){print $3,$2;}else{print;}}' - student.data |
|
||||
-- awk 'BEGIN{FS=" ";}{if(NF!=2){print $4,$5;}else{print;}}' - stud_emp.data
|
||||
--
|
||||
-- SELECT name, age FROM person*; ??? check if different
|
||||
SELECT p.name, p.age FROM person* p;
|
||||
|
||||
--
|
||||
-- awk '{print $1,$2;}' person.data |
|
||||
-- awk '{if(NF!=2){print $3,$2;}else{print;}}' - emp.data |
|
||||
-- awk '{if(NF!=2){print $3,$2;}else{print;}}' - student.data |
|
||||
-- awk 'BEGIN{FS=" ";}{if(NF!=1){print $4,$5;}else{print;}}' - stud_emp.data |
|
||||
-- sort +1nr -2
|
||||
--
|
||||
SELECT p.name, p.age FROM person* p ORDER BY age using >, name;
|
||||
|
||||
--
|
||||
-- Test some cases involving whole-row Var referencing a subquery
|
||||
--
|
||||
select foo from (select 1 offset 0) as foo;
|
||||
select foo from (select null offset 0) as foo;
|
||||
select foo from (select 'xyzzy',1,null offset 0) as foo;
|
||||
|
||||
--
|
||||
-- Test VALUES lists
|
||||
--
|
||||
select * from onek, (values(147, 'RFAAAA'), (931, 'VJAAAA')) as v (i, j)
|
||||
WHERE onek.unique1 = v.i and onek.stringu1 = v.j;
|
||||
|
||||
-- a more complex case
|
||||
-- looks like we're coding lisp :-)
|
||||
select * from onek,
|
||||
(values ((select i from
|
||||
(values(10000), (2), (389), (1000), (2000), ((select 10029))) as foo(i)
|
||||
order by i asc limit 1))) bar (i)
|
||||
where onek.unique1 = bar.i;
|
||||
|
||||
-- try VALUES in a subquery
|
||||
select * from onek
|
||||
where (unique1,ten) in (values (1,1), (20,0), (99,9), (17,99))
|
||||
order by unique1;
|
||||
|
||||
-- VALUES is also legal as a standalone query or a set-operation member
|
||||
VALUES (1,2), (3,4+4), (7,77.7);
|
||||
|
||||
VALUES (1,2), (3,4+4), (7,77.7)
|
||||
UNION ALL
|
||||
SELECT 2+2, 57
|
||||
UNION ALL
|
||||
TABLE int8_tbl;
|
||||
|
||||
--
|
||||
-- Test ORDER BY options
|
||||
--
|
||||
|
||||
CREATE TEMP TABLE foo (f1 int);
|
||||
|
||||
INSERT INTO foo VALUES (42),(3),(10),(7),(null),(null),(1);
|
||||
|
||||
SELECT * FROM foo ORDER BY f1;
|
||||
SELECT * FROM foo ORDER BY f1 ASC; -- same thing
|
||||
SELECT * FROM foo ORDER BY f1 NULLS FIRST;
|
||||
SELECT * FROM foo ORDER BY f1 DESC;
|
||||
SELECT * FROM foo ORDER BY f1 DESC NULLS LAST;
|
||||
|
||||
-- check if indexscans do the right things
|
||||
CREATE INDEX fooi ON foo (f1);
|
||||
SET enable_sort = false;
|
||||
|
||||
SELECT * FROM foo ORDER BY f1;
|
||||
SELECT * FROM foo ORDER BY f1 NULLS FIRST;
|
||||
SELECT * FROM foo ORDER BY f1 DESC;
|
||||
SELECT * FROM foo ORDER BY f1 DESC NULLS LAST;
|
||||
|
||||
DROP INDEX fooi;
|
||||
CREATE INDEX fooi ON foo (f1 DESC);
|
||||
|
||||
SELECT * FROM foo ORDER BY f1;
|
||||
SELECT * FROM foo ORDER BY f1 NULLS FIRST;
|
||||
SELECT * FROM foo ORDER BY f1 DESC;
|
||||
SELECT * FROM foo ORDER BY f1 DESC NULLS LAST;
|
||||
|
||||
DROP INDEX fooi;
|
||||
CREATE INDEX fooi ON foo (f1 DESC NULLS LAST);
|
||||
|
||||
SELECT * FROM foo ORDER BY f1;
|
||||
SELECT * FROM foo ORDER BY f1 NULLS FIRST;
|
||||
SELECT * FROM foo ORDER BY f1 DESC;
|
||||
SELECT * FROM foo ORDER BY f1 DESC NULLS LAST;
|
||||
|
||||
--
|
||||
-- Test planning of some cases with partial indexes
|
||||
--
|
||||
|
||||
-- partial index is usable
|
||||
explain (costs off)
|
||||
select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
|
||||
select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
|
||||
-- actually run the query with an analyze to use the partial index
|
||||
explain (costs off, analyze on, timing off, summary off)
|
||||
select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
|
||||
explain (costs off)
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
|
||||
-- partial index predicate implies clause, so no need for retest
|
||||
explain (costs off)
|
||||
select * from onek2 where unique2 = 11 and stringu1 < 'B';
|
||||
select * from onek2 where unique2 = 11 and stringu1 < 'B';
|
||||
explain (costs off)
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 < 'B';
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 < 'B';
|
||||
-- but if it's an update target, must retest anyway
|
||||
explain (costs off)
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 < 'B' for update;
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 < 'B' for update;
|
||||
-- partial index is not applicable
|
||||
explain (costs off)
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 < 'C';
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 < 'C';
|
||||
-- partial index implies clause, but bitmap scan must recheck predicate anyway
|
||||
SET enable_indexscan TO off;
|
||||
explain (costs off)
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 < 'B';
|
||||
select unique2 from onek2 where unique2 = 11 and stringu1 < 'B';
|
||||
RESET enable_indexscan;
|
||||
-- check multi-index cases too
|
||||
explain (costs off)
|
||||
select unique1, unique2 from onek2
|
||||
where (unique2 = 11 or unique1 = 0) and stringu1 < 'B';
|
||||
select unique1, unique2 from onek2
|
||||
where (unique2 = 11 or unique1 = 0) and stringu1 < 'B';
|
||||
explain (costs off)
|
||||
select unique1, unique2 from onek2
|
||||
where (unique2 = 11 and stringu1 < 'B') or unique1 = 0;
|
||||
select unique1, unique2 from onek2
|
||||
where (unique2 = 11 and stringu1 < 'B') or unique1 = 0;
|
||||
|
||||
--
|
||||
-- Test some corner cases that have been known to confuse the planner
|
||||
--
|
||||
|
||||
-- ORDER BY on a constant doesn't really need any sorting
|
||||
SELECT 1 AS x ORDER BY x;
|
||||
|
||||
-- But ORDER BY on a set-valued expression does
|
||||
create function sillysrf(int) returns setof int as
|
||||
'values (1),(10),(2),($1)' language sql immutable;
|
||||
|
||||
select sillysrf(42);
|
||||
select sillysrf(-1) order by 1;
|
||||
|
||||
drop function sillysrf(int);
|
||||
|
||||
-- X = X isn't a no-op, it's effectively X IS NOT NULL assuming = is strict
|
||||
-- (see bug #5084)
|
||||
select * from (values (2),(null),(1)) v(k) where k = k order by k;
|
||||
select * from (values (2),(null),(1)) v(k) where k = k;
|
||||
|
||||
-- Test partitioned tables with no partitions, which should be handled the
|
||||
-- same as the non-inheritance case when expanding its RTE.
|
||||
create table list_parted_tbl (a int,b int) partition by list (a);
|
||||
create table list_parted_tbl1 partition of list_parted_tbl
|
||||
for values in (1) partition by list(b);
|
||||
explain (costs off) select * from list_parted_tbl;
|
||||
drop table list_parted_tbl;
|
@ -7,6 +7,6 @@ describe('PostgresSQL Lexer tests', () => {
|
||||
const tokens = mysqlParser.getAllTokens(sql);
|
||||
|
||||
test('token counts', () => {
|
||||
expect(tokens.length - 1).toBe(12);
|
||||
expect(tokens.length).toBe(12);
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import PostgreSQLParserListener from '../../../src/lib/pgsql/PostgreSQLParserListener';
|
||||
import { Target_listContext } from '../../../src/lib/pgsql/PostgreSQLParser';
|
||||
import { PostgreSQLParserListener } from '../../../src/lib/pgsql/PostgreSQLParserListener';
|
||||
import PostgresSQL from '../../../src/parser/pgsql';
|
||||
|
||||
describe('PostgresSQL Listener Tests', () => {
|
||||
@ -10,10 +11,9 @@ describe('PostgresSQL Listener Tests', () => {
|
||||
|
||||
test('Listener enterTableName', async () => {
|
||||
let result = '';
|
||||
class MyListener extends PostgreSQLParserListener {
|
||||
// eslint-disable-next-line camelcase
|
||||
enterTable_ref = (ctx): void => {
|
||||
result = ctx.getText().toLowerCase();
|
||||
class MyListener implements PostgreSQLParserListener {
|
||||
enterTable_ref(ctx) {
|
||||
result = ctx.text.toLowerCase();
|
||||
}
|
||||
}
|
||||
const listenTableName: any = new MyListener();
|
||||
|
18
test/parser/pgsql/selectStatement.test.ts
Normal file
18
test/parser/pgsql/selectStatement.test.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import PostgresSQL from "../../../src/parser/pgsql";
|
||||
import { readSQL } from "../../helper";
|
||||
|
||||
const parser = new PostgresSQL();
|
||||
|
||||
const features = {
|
||||
base: readSQL(__dirname, "select.sql"),
|
||||
};
|
||||
|
||||
describe("Postgre SQL Query Statement Tests", () => {
|
||||
describe("Base Select", () => {
|
||||
features.base.forEach((sql) => {
|
||||
it(sql, () => {
|
||||
expect(parser.validate(sql).length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,10 +1,10 @@
|
||||
import PostgresSQL from "../../../src/parser/pgsql";
|
||||
|
||||
describe('Generic SQL Syntax Tests', () => {
|
||||
describe('PostgresSQL SQL Syntax Tests', () => {
|
||||
const parser = new PostgresSQL();
|
||||
|
||||
test('Select Statement', () => {
|
||||
const sql = 'select id,name from user1;';
|
||||
const sql = 'select id, t_name from user1;';
|
||||
const result = parser.validate(sql);
|
||||
|
||||
expect(result.length).toBe(0);
|
||||
@ -15,4 +15,11 @@ describe('Generic SQL Syntax Tests', () => {
|
||||
const result = parser.validate(sql);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
||||
test('Select 1+1', () => {
|
||||
const sql = 'SELECT 1+1;';
|
||||
const result = parser.validate(sql);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import PostgreSQLParserVisitor from "../../../src/lib/pgsql/PostgreSQLParserVisitor";
|
||||
import { AbstractParseTreeVisitor } from "antlr4ts/tree/AbstractParseTreeVisitor";
|
||||
import { PostgreSQLParserVisitor } from "../../../src/lib/pgsql/PostgreSQLParserVisitor";
|
||||
import PostgresSQL from "../../../src/parser/pgsql";
|
||||
|
||||
describe('Generic SQL Visitor Tests', () => {
|
||||
@ -12,11 +13,13 @@ describe('Generic SQL Visitor Tests', () => {
|
||||
|
||||
test('Visitor visitTableName', () => {
|
||||
let result = '';
|
||||
class MyVisitor extends PostgreSQLParserVisitor<any> {
|
||||
// eslint-disable-next-line camelcase
|
||||
visitTable_ref = (ctx): void => {
|
||||
result = ctx.getText().toLowerCase();
|
||||
super.visitTable_ref?.(ctx);
|
||||
class MyVisitor extends AbstractParseTreeVisitor<any> implements PostgreSQLParserVisitor<any> {
|
||||
protected defaultResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
visitTable_ref(ctx) {
|
||||
result = ctx.text.toLowerCase();
|
||||
}
|
||||
}
|
||||
const visitor: any = new MyVisitor();
|
||||
|
Reference in New Issue
Block a user