40c911597b
* feat: improve keywords definations and add prefix named KW_ * test: capitalize keywords in alter sql test cases * test: capitalize keywords in create sql test cases * feat: merge interval rule and timeIntervalExpression rule in flinksql grammar * test: put keywords in quotation marks around insert sql test cases * test: put keywords in quotation marks around select sql test cases * feat: improve uid rule * test: rename sum to _sum because it is a reserved keyword * docs: improve comments in flinkSqlLexer
234 lines
8.1 KiB
TypeScript
234 lines
8.1 KiB
TypeScript
import FlinkSQL from '../../../src/parser/flinksql';
|
||
|
||
describe('FlinkSQL Syntax Tests', () => {
|
||
const parser = new FlinkSQL();
|
||
|
||
// query statements
|
||
test('Test With clause', () => {
|
||
const sql = `
|
||
WITH orders_with_total AS (
|
||
SELECT order_id, price + tax AS total
|
||
FROM Orders
|
||
)
|
||
SELECT order_id, SUM(total)
|
||
FROM orders_with_total
|
||
GROUP BY order_id;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
test('Test simple Select Statement', () => {
|
||
const sql = `SELECT product, amount FROM Orders;`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
test('Test simple Error Select Statement', () => {
|
||
const sql = `SELECTproduct, amount FROM;`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(1);
|
||
});
|
||
test('Test Select Statement with where clause', () => {
|
||
const sql = `SELECT * FROM person WHERE id = 200 OR id = 300;`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
test('Test Select Statement with group by clause', () => {
|
||
const sql = `SELECT id, sum(quantity) FROM dealer GROUP BY id;`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
test('Test Select Statement with having clause', () => {
|
||
const sql = `
|
||
SELECT city, sum(quantity) AS _sum
|
||
FROM dealer GROUP BY city HAVING city = 'Fremont';
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
test('Test Select Statement with order by clause', () => {
|
||
const sql = `SELECT name, age FROM person ORDER BY age;`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
test('Test Select Statement with limit clause', () => {
|
||
const sql = `SELECT name, age FROM person ORDER BY name LIMIT 2;`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
test('Test Select Statement with join', () => {
|
||
const sql = `
|
||
SELECT id, name, employee.deptno, deptname FROM employee
|
||
FULL JOIN department ON employee.deptno = department.deptno;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
// test left outer join
|
||
test('Test Select Statement with left outer join', () => {
|
||
const sql = `
|
||
SELECT order_id, res
|
||
FROM Orders
|
||
LEFT OUTER JOIN LATERAL TABLE(table_func(order_id)) t(res)
|
||
ON TRUE
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
// test cross join
|
||
test('Test Select Statement with cross join', () => {
|
||
const sql = `
|
||
SELECT order_id, tag
|
||
FROM Orders CROSS JOIN UNNEST(tags) AS t (tag)
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
// test for time temporal join
|
||
test('Test Select Statement with time temporal join', () => {
|
||
const sql = `SELECT o.order_id, o.total, c.country, c.zip
|
||
FROM Orders AS o
|
||
JOIN Customers FOR SYSTEM_TIME AS OF o.proc_time AS c
|
||
ON o.customer_id = c.id;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
// test for catalog table
|
||
test('Test Select Statement with catalog table', () => {
|
||
const sql = `SELECT * FROM catalog1.db1.table1;`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
// describe statements
|
||
test('Test simple Describe Statement', () => {
|
||
const sql = `
|
||
DESCRIBE Orders;
|
||
DESC Orders;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
// explain statements
|
||
test('Test simple Explain Statement', () => {
|
||
const sql = `
|
||
EXPLAIN SELECT * FROM emps;
|
||
EXPLAIN PLAN FOR SELECT * FROM emps;
|
||
EXPLAIN PLAN FOR insert into emps1 SELECT * FROM emps2;
|
||
EXPLAIN CHANGELOG_MODE SELECT * FROM emps;
|
||
EXPLAIN ESTIMATED_COST SELECT * FROM emps;
|
||
EXPLAIN JSON_EXECUTION_PLAN SELECT * FROM emps;
|
||
EXPLAIN CHANGELOG_MODE, JSON_EXECUTION_PLAN, ESTIMATED_COST SELECT * FROM emps;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
// explain insert_statement
|
||
test('Test Explain Insert Statement', () => {
|
||
const sql = `EXPLAIN INSERT INTO EMPS1 SELECT * FROM EMPS2;`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
test('Test simple Explain statement_set', () => {
|
||
// 按官网上写的,那应该是 explain execute statement set - begin,但实际执行时,携带 execute 会报错
|
||
// 个人理解,explain 是解析该语法如何执行,而不能在解析的过程中,去执行语句
|
||
const sql = `
|
||
EXPLAIN STATEMENT SET
|
||
BEGIN
|
||
INSERT INTO t1 SELECT * FROM t2;
|
||
INSERT INTO t2 SELECT * FROM t3;
|
||
END;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
// use statements
|
||
test('Test simple Use Statement', () => {
|
||
const sql = `
|
||
USE CATALOG cat1;
|
||
USE db1;
|
||
USE MODULES hive;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
// show statements
|
||
test('Test simple Show Statement', () => {
|
||
const sql = `
|
||
SHOW CATALOGS;
|
||
SHOW CURRENT CATALOG;
|
||
SHOW DATABASES;
|
||
SHOW CURRENT DATABASE;
|
||
SHOW TABLES;
|
||
SHOW TABLES FROM catalog1.db1 NOT LIKE '%';
|
||
SHOW CREATE TABLE my_table;
|
||
SHOW COLUMNS FROM my_table LIKE '%f%';
|
||
SHOW VIEWS;
|
||
SHOW CREATE VIEW my_view;
|
||
SHOW FUNCTIONS;
|
||
SHOW USER FUNCTIONS;
|
||
SHOW MODULES;
|
||
SHOW FULL MODULES;
|
||
SHOW JARS;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
// other statement
|
||
test('Test other Statement', () => {
|
||
const sql = `
|
||
LOAD MODULE CORE;
|
||
LOAD MODULE dummy WITH ('k1' = 'v1', 'k2' = 'v2');
|
||
UNLOAD MODULE CORE;
|
||
SET;
|
||
SET 'test-key' = 'test-value';
|
||
RESET;
|
||
RESET 'test-key';
|
||
ADD JAR '<path_to_filename>.jar'
|
||
REMOVE JAR '<path_to_filename>.jar'
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
test('DT Add Statement', () => {
|
||
const sql = `
|
||
ADD JAR WITH /home/test.jar;
|
||
ADD JAR WITH /home/test.jar AS test.jar;
|
||
ADD FILE WITH /home/admin/sftp/dttest_cn/DsCenter_1687/krb5.conf AS krb5.conf;
|
||
ADD FILE WITH /home/admin/sftp/dttest_cn/DsCenter_1687/krb5.conf RENAME test.conf;
|
||
ADD PYTHON_FILES WITH /test.py RENAME test.py;
|
||
ADD PYTHON_REQUIREMENTS WITH /requirements.txt RENAME requirements.txt;
|
||
ADD PYTHON_JAR WITH /python_jar.jar RENAME py_jar.jar;
|
||
ADD PYTHON_PARAMETER /parameter.py;
|
||
ADD ENGINE FILE WITH /filePath RENAME theName KEY theKey;
|
||
`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
test('Test invalid Double Line Comment statement', () => {
|
||
const sql = `-test comment\n`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(1);
|
||
});
|
||
|
||
test('Test valid Double Line Comment statement', () => {
|
||
const sql = `----test comment\n`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
|
||
test('Test valid Hash Sign Line Comment statement', () => {
|
||
const sql = `#test comment\n`;
|
||
const result = parser.validate(sql);
|
||
expect(result.length).toBe(0);
|
||
});
|
||
});
|